2022 年 10 月 18 日に開催される Firebase Summit に、直接会場で、またはオンラインでご参加ください。Firebase を使用してアプリ開発を加速させ、自信を持ってアプリをリリースし、簡単にスケールする方法をご紹介します。 今すぐ登録

クラウドタスクで関数をエンキューします

コレクションでコンテンツを整理 必要に応じて、コンテンツの保存と分類を行います。

タスク キュー関数は、Google Cloud Tasksを利用して、アプリがメインのアプリケーション フローの外部で、時間のかかる、リソース集約型の、または帯域幅が制限されたタスクを非同期に実行できるようにします。

たとえば、レート制限のある API で現在ホストされている大量の画像ファイル セットのバックアップを作成するとします。その API の責任ある消費者になるためには、そのレート制限を尊重する必要があります。さらに、この種の長時間実行ジョブは、タイムアウトやメモリ制限により、障害に対して脆弱になる可能性があります。

この複雑さを軽減するために、 scheduleTimedispatchDeadlineなどの基本的なタスク オプションを設定するタスク キュー関数を作成し、その関数を Cloud Tasks のキューに渡すことができます。 Cloud Tasks 環境は、この種の操作に対して効果的な輻輳制御と再試行ポリシーを保証するように特別に設計されています。

Cloud Functions for Firebase v3.20.1 以降の Firebase SDK は、Firebase Admin SDK v10.2.0 以降と相互運用して、タスク キュー機能をサポートします。

Firebase でタスク キュー関数を使用すると、Cloud Tasks の処理に料金が発生する場合があります。詳細については、 Cloud Tasks の料金をご覧ください。

タスク キュー関数の作成

タスク キュー機能を使用するには、次のワークフローに従います。

  1. Firebase SDK for Cloud Functions を使用してタスク キュー関数を記述します。
  2. Firebase Local Emulator Suite を使用して関数をテストします。
  3. Firebase CLI を使用して関数をデプロイします。タスク キュー関数を初めてデプロイするとき、CLI は、ソースコードで指定されたオプション (レート制限と再試行) を使用して、Cloud Tasks にタスク キューを作成します。
  4. 新しく作成されたタスク キューにタスクを追加し、必要に応じてパラメーターを渡して実行スケジュールを設定します。これを実現するには、Admin SDK を使用してコードを記述し、それを Cloud Functions for Firebase にデプロイします。

タスク キュー関数の作成

onTaskDispatchedを使用して、タスク キュー関数の作成を開始します。タスク キュー関数を記述する際の重要な部分は、キューごとの再試行とレート制限の構成を設定することです。このページのコード サンプルは、NASA のAstronomy Picture of the Dayからすべての画像をバックアップするサービスを設定するアプリに基づいています。

タスク キューの構成

タスク キュー機能には、レート制限とタスク キューの再試行動作を正確に制御するための強力な構成設定のセットが付属しています。

exports.backupapod = onTaskDispatched(
    {
      retryConfig: {
        maxAttempts: 5,
        minBackoffSeconds: 60,
      },
      rateLimits: {
        maxConcurrentDispatches: 6,
      },
    }, async (req) => {
  • retryConfig.maxAttempts=5 : タスク キュー内の各タスクは、最大 5 回まで自動的に再試行されます。これにより、ネットワーク エラーや依存する外部サービスの一時的なサービス中断などの一時的なエラーを軽減できます。
  • retryConfig.minBackoffSeconds=60 : 各タスクは、各試行から少なくとも 60 秒間隔で再試行されます。これにより、各試行の間に大きなバッファーが提供されるため、急いで 5 回の再試行を使い果たすことはありません。
  • rateLimits.maxConcurrentDispatch=6 : 特定の時間に最大 6 つのタスクがディスパッチされます。これにより、基礎となる関数へのリクエストの安定したストリームを確保し、アクティブなインスタンスとコールド スタートの数を減らすことができます。

Firebase Local Emulator Suite を使用してタスク キュー機能をテストする

Firebase Local Emulator Suite のタスク キュー関数は、単純な HTTP 関数として公開されています。 JSON データ ペイロードを含む HTTP POST 要求を送信することで、エミュレートされたタスク関数をテストできます。

 # start the Local Emulator Suite
 firebase emulators:start

 # trigger the emulated task queue function
 curl \
  -X POST                                            # An HTTP POST request...
  -H "content-type: application/json" \              # ... with a JSON body
  http://localhost:$PORT/$PROJECT_ID/$REGION/$NAME \ # ... to function url
  -d '{"data": { ... some data .... }}'              # ... with JSON encoded data

タスクキュー機能の導入

Firebase CLI を使用してタスク キュー機能をデプロイします。

$ firebase deploy --only functions:backupapod

タスク キュー関数を初めてデプロイするとき、CLI は、ソースコードで指定されたオプション (レート制限と再試行) を使用して、Cloud Tasks にタスク キューを作成します。

関数のデプロイ時に権限エラーが発生した場合は、デプロイ コマンドを実行しているユーザーに適切なIAM ロールが割り当てられていることを確認してください。

関数をキューに入れる

タスク キュー関数は、Node.js 用の Firebase Admin SDK を使用して、Cloud Functions for Firebase などの信頼できるサーバー環境から Cloud Tasks でキューに入れることができます。 Admin SDK を初めて使用する場合は、「 Firebase をサーバーに追加する」を参照して開始してください。

一般的なフローでは、Admin SDK は新しいタスクを作成し、それを {cloudtasks_name}} でキューに入れ、タスクの構成を設定します。

exports.enqueueBackuptasks = onRequest(
async (_request, response) => {
  const queue = getFunctions().taskQueue("backupApod");
  const enqueues = [];
  for (let i = 0; i <= 10; i += 1) {
    # Enqueue each task with i*60 seconds day. Our task queue function
    # should process ~1 task/min.
    const scheduleDelaySeconds = i * 60 
    enqueues.push(
        queue.enqueue(
          { id: `task-${i}` },
          {
            scheduleDelaySeconds,
            dispatchDeadlineSeconds: 60 * 5 // 5 minutes
          },
        ),
    );
  }
  await Promise.all(enqueues);
  response.sendStatus(200);

});
  • scheduleDelaySeconds : サンプル コードは、N 番目のタスクに N 分の遅延を関連付けることで、タスクの実行を分散しようとします。これは、〜 1 タスク/分をトリガーすることを意味します。 Cloud Tasks で特定の時間にタスクをトリガーする場合は、 scheduleTimeを使用することもできます。
  • dispatchDeadlineSeconds : Cloud Tasks がタスクの完了を待機する最大時間。 Cloud Tasks は、キューの再試行構成に従って、またはこの期限に達するまで、タスクを再試行します。サンプルでは、​​タスクを最大 5 回再試行するようにキューが構成されていますが、プロセス全体 (再試行を含む) に 5 分以上かかると、タスクは自動的にキャンセルされます。

ターゲット URI を取得して含める

Cloud Functions for Firebase v2 は決定論的な HTTP URL をサポートしていないため、ターゲット URI を手動で取得して、キューに入れられた各タスクに含める必要があります。以下に示すように、関数の URL をプログラムで取得することもできます。

/**
 * Get the URL of a given v2 cloud function.
 *
 * @param {string} name the function's name
 * @param {string} location the function's location
 * @return {Promise<string>} The URL of the function
 */
async function getFunctionUrl(name, location="us-central1") {
  if (!auth) {
    auth = new GoogleAuth({
      scopes: "https://www.googleapis.com/auth/cloud-platform",
    });
  }
  const projectId = await auth.getProjectId();
  const url = "https://cloudfunctions.googleapis.com/v2beta/" +
    `projects/${projectId}/locations/${location}/functions/${name}`;

  const client = await auth.getClient();
  const res = await client.request({url});
  const uri = res.data?.serviceConfig?.uri;
  if (!uri) {
    throw new Error(`Unable to retreive uri for function at ${url}`);
  }
  return uri;
}

トラブルシューティング

Cloud Tasks のログを有効にする

Cloud Tasks からのログには、タスクに関連付けられたリクエストのステータスなど、有用な診断情報が含まれています。デフォルトでは、プロジェクトで大量のログが生成される可能性があるため、Cloud Tasks からのログはオフになっています。タスク キュー関数を積極的に開発およびデバッグしている間は、デバッグ ログをオンにすることをお勧めします。ロギングをオンにするを参照してください。

IAM 権限

タスクをキューに入れるとき、または Cloud Tasks がタスク キュー関数を呼び出そうとするときに、 PERMISSION DENIEDエラーが表示されることがあります。プロジェクトに次の IAM バインディングがあることを確認します。

gcloud projects add-iam-policy-binding $PROJECT_ID \
  --member=serviceAccount:${PROJECT_ID}@appspot.gserviceaccount.com \
  --role=roles/cloudtasks.enqueuer
  • Cloud Tasks にタスクをエンキューするために使用される ID には、Cloud Tasks のタスクに関連付けられたサービス アカウントを使用する権限が必要です。

    サンプルでは、​​これはApp Engine のデフォルトのサービス アカウントです。

App Engine のデフォルト サービス アカウントのユーザーとして App Engine のデフォルト サービス アカウントを追加する方法については、 Google Cloud IAM のドキュメントを参照してください。

gcloud functions add-iam-policy-binding $FUNCTION_NAME \
  --region=us-central1 \
  --member=serviceAccount:${PROJECT_ID}@appspot.gserviceaccount.com \
  --role=roles/cloudfunctions.invoker