Cloud Tasksを使ってみた
はじめに
Cloud Tasksで下記を試したときの備忘録です。
- cloud taskを動かす
- リトライ処理の確認
Cloud Tasksとは
完全マネージド型のメッセージキューサービスです。
大量のタスクの分散実行や配信管理、リトライ処理を行うことが可能です。(違いは結構ありますが、)AWSのSQSと似たようなサービスです。
以下はサービスのイメージをまとめてみました。
まず最初に用語の確認をしておきます。
用語整理
- タスク
1処理を実行するためのメッセージ - キュー
複数のタスクを管理するもの - タスクハンドラ(ワーカー)
タスクを処理するサービス
下記は全体の流れです。
- タスク作成のアプリケーションがタスクを作製してキューに送る
- キューは設定されたタスクを管理して、キューの設定に従いタスクハンドラーに配信(dispatch)する
- タスクハンドラーは処理を実行する
実行するハンドラを指定するのは、タスク作製時です。
つまり同じキューに入れても別々のハンドラに送信することが可能です。
事前準備
最初にタスクを実行するハンドラー作製します。今回はCloud functionを使用します。
index.js
にログを出力するだけの関数を作成します。
Taskを作成する際、bodyに値を追加することができるので内容が正しく渡せているかをログで確認します。
適当なディレクトリにindex.js
を作製します。
exports.taskHandler1 = (req, res) => {
console.info("body:", req.body)
res.status(200).send("taskHandler1 called!!");
}
作成できたら、deployします。
$ gcloud functions deploy taskHandler1 --runtime=nodejs12 --trigger-http --region asia-northeast1
// 正しくデプロイできたかを確認
$ curl https://asia-northeast1-${PROJECT}.cloudfunctions.net/taskHandler1
taskHandler1 called!!
Queueの作成
次はキューの作成します。
gcloud tasks queues create testQueue1
作製が完了したら次のコマンドで内容を確認できます。
gcloud tasks queues describe testQueue1
name: projects/${PROJECT}/locations/asia-northeast1/queues/testQueue1
rateLimits:
maxBurstSize: 100
maxConcurrentDispatches: 1000
maxDispatchesPerSecond: 500.0
retryConfig:
maxAttempts: 100
maxBackoff: 3600s
maxDoublings: 16
minBackoff: 0.100s
state: RUNNING
キューの構成についてはこちらの公式ドキュメントから確認できます。
Taskの作成
動作確認
実際にタスクを作成します。今回は、gcloud
を使います。
言語別のサンプルコードはこちらの公式ドキュメントに載っています。
--queue
にキュー名、--url
にハンドラ(先程作成したcloud fucntions)のURLを記載します。
--body-content
に追加した値が、ハンドラのbodyで受け取れます。
$ gcloud tasks create-http-task \
--queue=testQueue1 \
--url=https://asia-northeast1-${PROJECT}.cloudfunctions.net/taskHandler1 \
--header=content-type:application/json \
--body-content='{"Name":"sensuikan1973", "Age":"100"}'
実行後のcloud functionのログです。実行されていることが分かり、bodyの内容も表示されています。
タスクの重複管理
タスクにはタスクIDを指定できます。タスクIDを指定するとタスクの重複管理が可能です。
// タスクIDをtaskid1とする
$ gcloud tasks create-http-task taskid1 \
--queue=testQueue1 \
--url=https://asia-northeast1-${PROJECT}.cloudfunctions.net/taskHandler1 \
--header=content-type:application/json \
--body-content='{"Name":"sensuikan1973", "Age":"100"}'
// 同様のタスクを追加する
$ gcloud tasks create-http-task taskid1 \
--queue=testQueue1 \
--url=https://asia-northeast1-${PROJECT}.cloudfunctions.net/taskHandler1 \
--header=content-type:application/json \
--body-content='{"Name":"sensuikan1973", "Age":"100"}'
// 重複タスクは追加できず、エラーとなる
ERROR: (gcloud.tasks.create-http-task) ALREADY_EXISTS: Requested entity already exists
重複管理には制約があるので注意が必要です。
例えばタスクが削除または実行されてから 1時間は、同じ名前の別のタスクを作成することができません。
追加しようとすると次のエラーが発生します。
ERROR: (gcloud.tasks.create-http-task) ALREADY_EXISTS: The task cannot be created because a task with this name existed too recently.
詳細はこちらのドキュメントを確認してみてください。
リトライ処理
HTTPのハンドラを実行した場合、10分以内に200系のレスポンスを返さないと再試行が行われます。
リトライ処理を確認するため、レスポンスコードを400
を返すようにします。
exports.taskHandler1 = (req, res) => {
console.info("body:", req.body)
res.status(400).send("taskHandler1 called!!");
}
再度デプロイします。
gcloud functions deploy taskHandler1 --runtime=nodejs12 --trigger-http --region asia-northeast1
また、リトライ処理が分かりやすいようキューの設定を変更します。
$ gcloud tasks queues update testQueue1 \
--max-attempts 6 \
--min-backoff 5s \
--max-doublings 3
$ gcloud tasks queues describe testQueue1
rateLimits:
maxBurstSize: 100
maxConcurrentDispatches: 1000
maxDispatchesPerSecond: 500.0
retryConfig:
maxAttempts: 6
maxBackoff: 3600s
maxDoublings: 3
minBackoff: 5s
state: RUNNING
// タスクを実行
$ gcloud tasks create-http-task \
--queue=testQueue1 \
--url=https://asia-northeast1-${PROJECT}.cloudfunctions.net/taskHandler1 \
--header=content-type:application/json \
--body-content='{"Name":"sensuikan1973", "Age":"100"}'
最大試行回数の6回実行されています。
5s -> 10s -> 20s -> 40s -> 80s の間隔で再実行が行われています。
これはmaxDoublings(最大倍数回数)を3に指定しているため、最初の3回は実行時間が2倍になり、その後はリトライ時間は前回分が加算されます。
今回の例が分かりづらかったですが、今後は次の間隔で再実行されてきます。
5s -> 10s -> 20s -> 40s -> 80s -> 160s -> 240s -> ...
おわりに
GCPは最近触り始めたのですが、やってみた系の日本語ドキュメントはAWSに比べて少ないですね。
クラスメソッド developers.ioは偉大であることを認識できました。
Discussion