本文へ移動
Step 08 · Async backbone

Pub/Sub + Eventarc + Cloud TasksAsync messaging backbone

松葉のサービス同士を疎結合に繋ぐ「非同期メッセージング基盤」を整備しました。Pub/Sub はクラウド版の「掲示板+購読者」、Eventarc は「ストレージの変更を即座にスキャナに伝える専用線」、Cloud Tasks は「メール送信をキュー越しに非同期化する HTTP ジョブ」です。

所要時間: 40 分 前提条件: Step 06 + Step 07 後続: Step 09
01

本手順で作成したものの規模感By the numbers

Topics
13 + 13主 / DLQ

業務イベント用と、配信失敗の退避先 DLQ を 1 対 1 で用意。

Subscriptions
22個

主購読 9(Push + OIDC)+ DLQ 監視用 13(Pull)。

Eventarc Trigger
1トリガ

未検査バケットの変更 → scanner を起動。

Cloud Tasks Queue
1キュー

notification-queue(メール送信ジョブの非同期化)。

02

業務イベント Topic 一覧 · 13 種Business topics

ファイル / フォルダ / 共有リンク / Box の状態変化を、それぞれ独立した topic に publish します。受信側は必要な topic だけ subscribe するので、サービス追加・削除が他サービスに影響しません。

Topic発火元購読者の業務内容
file.uploadedmatsuba-apiアップロード完了(トレース用、subscriber 無し)
file.scan_cleanmatsuba-scannermatsuba-sync が Drive 同期を起動
file.scan_infectedmatsuba-scannermatsuba-api が感染通知メールを送る
file.replacedmatsuba-apiDrive 側を新世代に更新
file.deleted_soft / folder.deleted_softmatsuba-api論理削除(30 日後の物理削除まで no-op)
file.deleted_hard / folder.deleted_hardmatsuba-batchDrive ゴミ箱に送る
folder.created / folder.renamedmatsuba-apiDrive 側にフォルダ作成 / 改名を反映
share.createdmatsuba-api受取人にメール送付
share.accessedmatsuba-api監査用(subscriber 無し、publish のみで audit_logs に既に記録済)
box.drive_sync_toggledmatsuba-apiDrive 同期 ON/OFF の切替
03

配信失敗を取りこぼさない DLQ 設計Dead Letter Queue

Pub/Sub は配信保証が「最低 1 回」のため、受信側で重複排除を実装します。一方、配信が 上限回数まで連続して失敗したメッセージは「DLQ(退避キュー)」に流して保持します。13 トピック全てに 1 対 1 で DLQ topic + 監視用 pull subscription を用意し、後で手動再投入できる構成にしました。

図 · 失敗メッセージは DLQ topic → DLQ subscription で保全
matsuba-apipublishertopic: file.scan_clean業務イベント topicsub: -sub-syncPush · OIDC 認証 · 上限回数まで再試行matsuba-syncsubscriberDLQ topic: .dlq上限到達で自動退避DLQ sub: .dlq-subPull · 有効期限なし · 件数監視のみ配信失敗(上限回数)dlq-monitor5 分毎に件数監視しきい値超過 → app_alerts に起票 → system_admin にメール通知 → /admin/sync 画面から手動再投入

同じ構造を 13 セット用意: 上図は file.scan_clean 1 トピック分ですが、同じ構造を 13 種類全てに対して用意しています(主購読の有無は経路毎に違いますが、DLQ + DLQ pull subscription は 13 全件)。Pub/Sub のドキュメントが「DLQ topic を作っただけではメッセージが消失する」と明記しているため、必ず pull subscription で保全しています。

04

Eventarc トリガStorage to scanner

Eventarc は「クラウド内の出来事(イベント)を Cloud Run に Push する」専用の連携サービスです。本構築では 未検査バケットへのファイル追加を即座にスキャナ Cloud Run に通知する 1 本だけ作成しました。

項目値
トリガ名unscanned-finalize-to-scanner
監視対象未検査バケット
イベントタイプgoogle.cloud.storage.object.v1.finalized(ファイル作成完了)
宛先matsuba-scanner の /eventarc/finalized エンドポイント
SAscanner の実行 SA
配送遅延 SLOP95 で数秒以内を目標(ファイル追加から数秒以内に scanner が起動)
05

Cloud Tasks Queue notification-queueMail enqueue

通知メール送信は「画面操作に対する即時応答」よりも「確実に送り終える」を優先したいため、メール送信処理は Cloud Tasks キューに enqueue(仕事を並ばせる)し、matsuba-api 内のワーカールートが順次処理する設計です。Resend のレート制限を超えないよう、最大ディスパッチ数に上限を設定しました。

項目値
キュー IDnotification-queue
ロケーションasia-northeast1
最大ディスパッチレート上限を設定(Resend のレート制限内)
最大同時ディスパッチ数上限を設定
最大試行回数上限回数を設定
最大試行時間上限時間を設定(超えたら失敗確定)
バックオフ指数バックオフ
06

SA × Topic / Subscription への権限Per-resource IAM

Pub/Sub は トピック単位 / サブスクリプション単位で IAM 権限を付与します。プロジェクト全体に pubsub.publisher を付ける近道は取らず、各 topic ごとに「この SA だけが publish できる」を厳守しました。

SA付与ロール対象
api の実行 SApubsub.publisher9 トピック(file.*, folder.*, share.*, box.*)
scanner の実行 SApubsub.publisher2 トピック(file.scan_clean / file.scan_infected)
batch(Jobs)の実行 SApubsub.publisher2 トピック(file.deleted_hard / folder.deleted_hard)
sync の実行 SApubsub.subscriber7 サブスクリプション(sync 側 Push 経路)
api の実行 SApubsub.subscriber2 サブスクリプション(通知系)