メッセージキュー型の非同期処理から Temporal 移行へ¶
チェック¶
- [ ] 本文を確認した
- [ ] 概要を確認した
- [ ] タグを確認した
- [ ]
inbox/直下へ移行した
概要¶
LayerXのマルチテナントバックエンドで、EventBridge、SQS、Worker、Connect RPCによる非同期処理基盤からTemporalへ移行する話。 同期APIと重い非同期処理のワークロード混在、状態永続化不足、リトライの自前実装を課題としている。 Temporal導入後の浸透策として、Protobufからのインフラコード生成、コンテキスト伝搬、Temporal向け認可トークンが扱われている。
本文¶
前提¶
対象は、複数のConnect RPCサーバーがドメインごとに稼働するマルチテナントバックエンド。 ドキュメント処理パイプラインやLLMを使った長時間処理など、重い非同期処理が日常的に存在する。
既存構成は EventBridge → SQS → Worker → Connect RPC。 通常のConnect RPCと同じ形で非同期処理を書ける利点はあるが、同期APIのレイテンシやスループットを非同期処理が悪化させる。 状態永続化がなく、途中再開やリトライロジックもアプリ側に寄る。
Temporal採用理由¶
- 同期処理と非同期処理のワークロードを物理的に分離できる
- Workflowの状態を永続化し、障害時に続きから再開できる
- WorkerとTask Queueで処理の分散とスケールを担保できる
- 実行状況、履歴、失敗リトライをWeb UIで追える
アーキテクチャ比較¶
検討案は大きく3つ。
- 既存Workerを拡張し、SQS WorkerからTemporalを起動する
- 各サービスから直接Workflowを起動する
- EventBridge → Lambda → Temporalの構成にする
採用は EventBridge → Lambda → Temporal。 理由は、キュー基盤をTemporal Task Queueに一元化し、既存Workerの責務肥大化を避け、1イベントから複数Workflowを起動する責務やリトライをEventBridge/Lambda側で吸収できるため。 EventBridgeがバッファになり、Temporal障害が発火元へ直接波及しにくい点も利点。
浸透のための取り組み¶
Protobufからのインフラコード生成¶
Workflow / ActivityのGoコードは protoc-gen-go-temporal で生成。
protobuf optionを使い、ルーティングコードを生成する内製protoc pluginを用意して、SourceからTemporalまでつなげる。
コンテキスト伝搬¶
テナントID、リクエストID、分散トレース情報など、1リクエスト内で引き回したい横断情報はTemporal境界でそのまま渡らない。
GoではTemporal SDKの ContextPropagator を内製ライブラリで提供し、Client、Workflow、Activityの境界でHeader経由で受け渡す。
TypeScriptではSDKのInterceptorとAsyncLocalStorageを使って同様の伝搬を行う。
Temporal向け認可トークン¶
Workflowは中断・再開を許容する長寿命処理で、Activityは何度もリトライされ得る。 通常の短命な認可トークンをそのまま使えないため、StartWorkflow時にWorkflow専用の長寿命認可トークンへ引き換え、Activity内で再度通常の認可トークンに引き換える方式を取る。
要点¶
- Temporal移行は「キュー置き換え」ではなく、状態永続化、可視性、リトライ、責務分離の設計変更。
- EventBridge → Lambda → Temporalは、発火元を疎結合にしつつTemporal Task Queueへ責務を寄せる構成。
- コンテキスト伝搬と認可トークンは、Temporalを実運用へ浸透させるための重要な周辺設計。