Cloud Tasksの最大同時実行ディスパッチの効果を検証してみる #cm_google_cloud_adcal_2024
はじめに
データ事業本部のkobayashiです。
クラスメソッドの Google Cloud Advent Calendar 2024 の 19 日目のブログです。
先日のCloud Workflowsで1つのワークフローを実行する際にCloud Taskキューを使用して実行レートの制限をしてみた記事の最後に書いた「最大同時ディスバッチ数で同一ワークフローの同時実行」は出来なかったのですが、では制御の行えるCloud Run関数のタスクを同じキューに混ぜた時にどういった挙動になるかが気になったのでためてみましたのでその内容をまとめます。
最大同時ディスバッチ数の挙動をCloud WorkflowsとCloud Run関数のタスクで確認する
最大同時ディスバッチ数ですがすでに記事にした通りCloud Workflowsでは効果がありませんでした。一方Cloud Run関数では同一関数の実行数を制御できます。詳しくはこちらの記事をご確認ください。
最大同時ディスバッチ数の設定に対してCloud WorkflowsとCloud Run関数のタスクで異なる挙動となるのでタスクを混ぜた場合にどのような挙動になるかを調べるために以下の方法で検証してみました。
- 最大同時ディスバッチ数を1に設定しCloud WorkflowsとCloud Run関数のタスクを交互にタスクに登録して実行してみる
- 最大同時ディスバッチ数を2に設定しCloud WorkflowsとCloud Run関数のタスクを交互にタスクに登録して実行してみる
- 最大同時ディスバッチ数を2に設定し2つのCloud Workflowsをと1つのCloud Run関数のタスクを交互にタスクに登録して実行してみる
ワークフローは前回作成した10秒間待機するものtest-wf-queue1
をそのまま使います。Cloud Tasksのキューも前回のものtest-wf-queue1
をそのまま使います。
Cloud Run関数ですがこちらも以下のようなコードを使用して10秒間待機する関数test-task
を作成します。
import time
import functions_framework
@functions_framework.http
def main(request):
request_json = request.get_json()
iteration = request_json.get("iteration")
print(f"Start task-{iteration}")
time.sleep(10)
print(f"Finish task-{iteration}")
return f"task-{iteration}"
functions-framework==3.*
それでは早速試してみます。
最大同時ディスバッチ数1
それでは先にCloud Tasksのキューの設定で最大同時ディスパッチ数を1に変更します。
$ gcloud tasks queues update test-wf-queue1 --location=asia-northeast1 \
--max-dispatches-per-second=500 --max-concurrent-dispatches=1 \
--log-sampling-ratio=1.0
なお、最大ディスパッチ数(1秒間に実行されるタスク数)は上限の500--max-dispatches-per-second=500
にしてこちらの影響は考えないものとします。また実行結果をCloud Loggingで確認するため--log-sampling-ratio=1.0
でログをすべて出力するようにしています。
次にワークフローとCloud Run関数を以下のshellスクリプトで交互に登録します。
#!/bin/bash
# 変数定義
QUEUE_NAME="test-wf-queue1"
LOCATION="asia-northeast1"
PROJECT_ID="{プロジェクトID}"
WORKFLOW_NAME="wf-task"
SERVICE_ACCOUNT="wf-sa-for-queue@{プロジェクトID}.iam.gserviceaccount.com"
ITERATIONS=10
for i in $(seq 1 $ITERATIONS); do
PADDED_NUM=$(printf "%03d" $i)
# UUIDの生成
TASK_UUID=$(uuidgen)
echo "Creating task $i of $ITERATIONS (UUID: $TASK_UUID)"
gcloud tasks create-http-task "task-${PADDED_NUM}-workflow-${TASK_UUID}" \
--queue=$QUEUE_NAME \
--location=$LOCATION \
--url="https://workflowexecutions.googleapis.com/v1/projects/$PROJECT_ID/locations/$LOCATION/workflows/$WORKFLOW_NAME/executions" \
--method=POST \
--oauth-token-scope="https://www.googleapis.com/auth/cloud-platform" \
--oauth-service-account-email=$SERVICE_ACCOUNT \
--body-content="{\"argument\": \"{\\\"iteration\\\": $i}\"}"
sleep 0.1
gcloud tasks create-http-task "task-${PADDED_NUM}-cloudrunfunc-${TASK_UUID}" \
--queue=$QUEUE_NAME \
--location=$LOCATION \
--url="https://asia-northeast1-$PROJECT_ID.cloudfunctions.net/test-task" \
--method=POST \
--oidc-service-account-email="$PROJECT_ID@appspot.gserviceaccount.com" \
--header="Content-Type: application/json" \
--body-content="{\"iteration\": $i}"
sleep 0.1
done
echo "Task creation completed"
キューに登録したタスクを確認してみると次にようにワークフローとCloud Run関数のタスクが交互に登録されていることが確認できます。
$ gcloud tasks list --queue=test-wf-queue1 --location=asia-northeast1 --sort-by=SCHEDULE_TIME
TASK_NAME TYPE CREATE_TIME SCHEDULE_TIME DISPATCH_ATTEMPTS RESPONSE_ATTEMPTS LAST_ATTEMPT_STATUS
task-001-workflow-8C62411B-263B-4D49-A5C1-8E1C46C6E646 http 2024-12-15T05:24:02Z 2024-12-15T05:24:02.080372Z 0 0 Unknown
task-001-cloudrunfunc-8C62411B-263B-4D49-A5C1-8E1C46C6E646 http 2024-12-15T05:24:02Z 2024-12-15T05:24:02.948595Z 0 0 Unknown
...
task-010-workflow-3863A950-3FF7-4594-BD2C-1AC814550A27 http 2024-12-15T05:24:16Z 2024-12-15T05:24:16.791385Z 0 0 Unknown
task-010-cloudrunfunc-3863A950-3FF7-4594-BD2C-1AC814550A27 http 2024-12-15T05:24:17Z 2024-12-15T05:24:17.581308Z 0 0 Unknown
では実行結果をCloud Logginのログエクスプローラーで見てみます。
使用するクエリは次のものです。
resource.type="cloud_tasks_queue" resource.labels.queue_id="test-wf-queue1" severity>=DEFAULT
jsonPayload.attemptDispatchLog.dispatchReason="PUSH_QUEUE"
jsonPayload.task:"projects/{プロジェクトID}/locations/asia-northeast1/queues/test-wf-queue1/tasks/"
結果を見てみるとワークフローが実行された後にCloud Run関数が実行され最大同時ディスバッチ数の1となりCloud Run関数の終了を待ちます。Cloud Run関数の実行に10秒かかるのでCloud Run関数の実行開始から10秒程度で次のワークフロー、Cloud Run関数が実行されこれを繰り返します。
最大同時ディスバッチ数2
それでは次に最大同時ディスバッチ数を2--max-concurrent-dispatches=2
にして同じ処理を行ってみます。
$ gcloud tasks queues update test-wf-queue1 --location=asia-northeast1 \
--max-concurrent-dispatches=2
これも結果は単純で、Cloud Run関数の実行数のみが最大同時ディスバッチ数の効果があるだけになります。結果を見ると
- ワークフロー
task-001-workflow
、Cloud Run関数task-001-cloudrunfunc
が実行され、この時点ではCloud Run関数の実行数が1となる - ワークフロー
task-002-workflow
、Cloud Run関数task-002-cloudrunfunc
が実行され、この時点でCloud Run関数の実行数が2になる - Cloud Run関数
task-001-cloudrunfunc
の終了を待ちで実行からおよそ10秒後にワークフローtask-003-workflow
、Cloud Run関数task-003-cloudrunfunc
が実行される - Cloud Run関数
task-002-cloudrunfunc
の終了を待ちで実行からおよそ10秒後にワークフローtask-004-workflow
、Cloud Run関数task-004-cloudrunfunc
が実行される
以降、これを繰り返します。
最大同時ディスパッチ数2(ワークフロー2、Cloud Run関数1)
最後に最大同時ディスパッチ数は2のままでCloud Workflowsのワークフローを2つ、Cloud Run関数を1つを繰り返し実行するパターンを検証してみます。
$ gcloud tasks list --queue=test-wf-queue1 --location=asia-northeast1 --sort-by=SCHEDULE_TIME
TASK_NAME TYPE CREATE_TIME SCHEDULE_TIME DISPATCH_ATTEMPTS RESPONSE_ATTEMPTS LAST_ATTEMPT_STATUS
task-001-a-workflow-2CACA3E5-E96B-42A9-B15A-62480ED3C587 http 2024-12-15T06:07:35Z 2024-12-15T06:07:35.261374Z 0 0 Unknown
task-001-b-workflow-2CACA3E5-E96B-42A9-B15A-62480ED3C587 http 2024-12-15T06:07:36Z 2024-12-15T06:07:36.126778Z 0 0 Unknown
task-001-cloudrunfunc-2CACA3E5-E96B-42A9-B15A-62480ED3C587 http 2024-12-15T06:07:36Z 2024-12-15T06:07:36.989334Z 0 0 Unknown
task-002-a-workflow-95DDB106-EC6B-49B4-9B96-7591AB1705E4 http 2024-12-15T06:07:37Z 2024-12-15T06:07:37.918163Z 0 0 Unknown
task-002-b-workflow-95DDB106-EC6B-49B4-9B96-7591AB1705E4 http 2024-12-15T06:07:38Z 2024-12-15T06:07:38.663005Z 0 0 Unknown
task-002-cloudrunfunc-95DDB106-EC6B-49B4-9B96-7591AB1705E4 http 2024-12-15T06:07:39Z 2024-12-15T06:07:39.540776Z 0 0 Unknown
task-003-a-workflow-D4E5E78D-902E-46AD-BB1C-1EDF62F83269 http 2024-12-15T06:07:40Z 2024-12-15T06:07:40.340936Z 0 0 Unknown
task-003-b-workflow-D4E5E78D-902E-46AD-BB1C-1EDF62F83269 http 2024-12-15T06:07:41Z 2024-12-15T06:07:41.244466Z 0 0 Unknown
...
これも結果を見てみます。結果は先程の最大同時ディスパッチ数2のパターンと同じでワークフローの実行は最大同時ディスパッチに関係のないものということだけです。
Cloud Run関数の実行数のみが最大同時ディスバッチ数の効果があるだけになります。結果を見ると
- ワークフロー
task-001-a-workflow
、ワークフローtask-001-b-workflow
、Cloud Run関数task-001-cloudrunfunc
が実行され、この時点ではCloud Run関数の実行数が1となる - ワークフロー
task-002-a-workflow
、ワークフローtask-002-b-workflow
、Cloud Run関数task-002-cloudrunfunc
が実行され、この時点でCloud Run関数の実行数が2になる - Cloud Run関数
task-001-cloudrunfunc
の終了を待ちで実行からおよそ10秒後にワークフローtask-003-a-workflow
、ワークフローtask-003-b-workflow
、Cloud Run関数task-003-cloudrunfunc
が実行される - Cloud Run関数
task-002-cloudrunfunc
の終了を待ちで実行からおよそ10秒後にワークフローtask-004-a-workflow
、ワークフローtask-004-b-workflow
、Cloud Run関数task-004-cloudrunfunc
が実行される
以降、これを繰り替える形です。
まとめ
Cloud Tasksの最大同時ディスパッチ数の挙動を確認してみました。3つの検証結果としては単純にCloud Workflowsの実行数は無視されCloud Run関数の同時実行数のみが影響するという内容でした。この検証結果を踏まえCloud Tasksのキューをうまく使っていきたいと思います。
明日 12/20 は suto さんです。お楽しみに。