- ユーザーがWeb API経由で「画像処理のリクエスト」(例: サムネイル作成指示)を送信
- そのリクエストがPub/Subに送られる
- バックエンドでは、別のワーカーがそのリクエストをPub/Subから受け取り、画像処理を模擬的に実行
- パブリッシャー (Publisher App):
- FastAPI を使ったシンプルなWeb API。
- ユーザーからのリクエスト(例:
/request_image_processing
エンドポイント)を受け付けます。 - リクエスト内容(例: 画像ファイル名、処理の種類など)をメッセージとしてPub/Subトピックに送信します。
- ユーザーにはすぐに「リクエストを受け付けました」と応答を返します(実際の処理完了を待たない)。
- サブスクライバー (Worker App):
- こちらもFastAPIを使ったシンプルなWebアプリケーション(Pub/SubのPushサブスクリプションで受信するため)。
- Pub/Subトピックからメッセージ(画像処理リクエスト)をPushで受信します。
- 受信したメッセージに基づいて、画像処理を模擬的に実行します(例: ログに処理内容を出力し、数秒待機する)。
- 処理が完了したらPub/SubにACK(確認応答)を返します。
- Pub/Sub:
- パブリッシャーとサブスクライバーの間でメッセージを仲介します。
学習できること:
- Pub/Subによる非同期処理の実現。
- アプリケーション間の疎結合化。
- PythonでのPub/Subライブラリの基本的な使い方(メッセージのパブリッシュ、Pushサブスクリプションでの受信)。
- Cloud Runとの連携(オプション)。
- Google Cloud プロジェクト:
- プロジェクトを作成または選択します。
- Pub/Sub API を有効にします。
- 課金を有効にします。
- Python環境:
- Python 3.7以上。
pip install google-cloud-pubsub flask
を実行してライブラリをインストールします。
- 認証:
- ローカル開発時:
gcloud auth application-default login
を実行して認証情報を設定します。また、PROJECT_IDを環境変数に設定しておきます。
gcloud auth application-default login export PROJECT_ID=$(gcloud config get-value project)
- Cloud Runデプロイ時: Cloud RunのサービスアカウントにPub/Subへのアクセス権限(Pub/Subパブリッシャー、Pub/Subサブスクライバーロールなど)が自動的に付与されるか、適切に設定します。
- ローカル開発時:
uv init
uv add google-cloud-pubsub fastapi "uvicorn[standard]"
gcloud pubsub topics create image-processing-requests
- パブリッシャーとサブスクライバーをCloud Runにデプロイ: それぞれのアプリケーションディレクトリでDockerfileとソースコードを用意し、以下のコマンドでデプロイします。
# Publisher Appのデプロイ
gcloud run deploy publisher-app \
--source . \
--platform managed \
--region asia-northeast1 \
--allow-unauthenticated \
--set-env-vars="GOOGLE_CLOUD_PROJECT=${PROJECT_ID}"
# Worker App (Subscriber) のデプロイ
gcloud run deploy worker-app \
--source . \
--platform managed \
--region asia-northeast1 \
--no-allow-unauthenticated
# Pub/Subからの呼び出しのみ許可
# worker_app.py と Dockerfile があるディレクトリで実行
デプロイ後、`publisher-app` および `worker-app` のURL を控えておきます。
- Pushサブスクリプションの作成:
worker-app
がPub/Subからのメッセージを受け取れるように、Pushサブスクリプションを作成します。
export PUBLISHER_APP_URL="YOUR_PUBLISHER_APP_URL" # 上で控えたPublisher AppのURL
export WORKER_APP_URL="YOUR_WORKER_APP_URL" # 上で控えたWorker AppのURL
# Pub/SubがCloud Run (worker-app) を呼び出すためのサービスアカウントを作成
# 1. Pub/Sub用のサービスアカウントを作成
gcloud iam service-accounts create pubsub-cloud-run-invoker --display-name "Pub/Sub Cloud Run Invoker"
export PUBSUB_SERVICE_ACCOUNT_EMAIL="pubsub-cloud-run-invoker@${PROJECT_ID}.iam.gserviceaccount.com"
# 2. Worker Appにそのサービスアカウントからの呼び出しを許可するロールを付与
gcloud run services add-iam-policy-binding worker-app \
--member="serviceAccount:${PUBSUB_SERVICE_ACCOUNT_EMAIL}" \
--role="roles/run.invoker" \
--platform managed --region asia-northeast1
# Pushサブスクリプションを作成
gcloud pubsub subscriptions create image-processing-subscription \
--topic image-processing-requests \
--push-endpoint="${WORKER_APP_URL}/" \
--ack-deadline=60
# pushエンドポイントとしてWorker Appのルートパスを指定
# Workerの最大処理時間より長く設定 (デフォルト10秒)
# サービスアカウントを指定
gcloud pubsub subscriptions update image-processing-subscription \
--push-endpoint="${WORKER_APP_URL}" \
--push-auth-service-account="pubsub-cloud-run-invoker@${PROJECT_ID}.iam.gserviceaccount.com" \
--project=${PROJECT_ID}
注意: --push-auth-service-account
を設定する場合、Worker AppのCloud Runサービスは --no-allow-unauthenticated
でデプロイされている必要があります。その上で、指定したサービスアカウントにWorker Appを呼び出す権限 (roles/run.invoker
) を付与する必要があります。簡単のため、最初は worker-app
を --allow-unauthenticated
でデプロイし、認証なしで試すこともできますが、本番環境では必ず認証を設定してください。
Publisher側動作確認
curl -X POST -H "Content-Type: application/json" \
-d '{"filename": "test_from_successful_deploy.jpg", "processing_type": "test_processing"}' \
${PUBLISHER_APP_URL}/request_image_processing
動作確認
$ curl -X POST -H "Content-Type: application/json" \ (main@pubsub-learn)
-d '{"filename": "my_vacation_photo.jpg", "processing_type": "create_thumbnail_small"}' \
${PUBLISHER_APP_URL}/request_image_processing
{"message":"Image processing request received.","message_id":"15030699850359131"}%
ログ確認
- Google Cloudのコンソール上からCloud Runを開き、wokerのログを確認する
{
insertId: ".........."
labels: {1}
logName: "projects/........../logs/run.googleapis.com%2Fstdout"
payload: "textPayload"
receiveLocation: "asia-northeast1"
receiveTimestamp: "2025-05-27T07:28:05.117513214Z"
resource: {2}
severity: "DEFAULT"
textPayload: "Received task (messageId: ............): Process 'create_thumbnail_small' for file 'my_vacation_photo.jpg'"
timestamp: "2025-05-27T07:28:04.878367Z"
traceSampled: false
}
- Cloud Run サービス (
publisher-app
,worker-app
) - Pub/Sub トピック (
image-processing-requests
) - Pub/Sub サブスクリプション (
image-processing-subscription
) - サービスアカウント (
pubsub-cloud-run-invoker@${PROJECT_ID}.iam.gserviceaccount.com
) - コンテナイメージ (Artifact Registry内)
- Google Cloudプロジェクト全体
完全に料金を発生させないようにするには、これらのリソースを削除するのが最も確実です。
これにより、サービスの実行に伴う料金が発生しなくなります。
# publisher-app の削除
gcloud run services delete publisher-app \
--platform managed \
--region asia-northeast1 \
--project=${PROJECT_ID} \
--quiet # 確認プロンプトをスキップする場合は --quiet を追加
# worker-app の削除
gcloud run services delete worker-app \
--platform managed \
--region asia-northeast1 \
--project=${PROJECT_ID} \
--quiet # 確認プロンプトをスキップする場合は --quiet を追加
(YOUR_DEPLOY_REGION
はサービスをデプロイしたリージョンに置き換えてください。)
--quiet
オプションを外すと、削除前に確認を求められます。
サブスクリプションが存在すると、メッセージの滞留や配信試行に関連するわずかながらコストが発生する可能性があるため、削除します。
gcloud pubsub subscriptions delete image-processing-subscription \
--project=${PROJECT_ID} \
--quiet
トピック自体はメッセージが保存されていなければ通常大きなコストはかかりませんが、クリーンアップのためには削除するのが良いでしょう。
gcloud pubsub topics delete image-processing-requests \
--project=${PROJECT_ID} \
--quiet
注意: トピックにまだサブスクリプションが関連付けられている場合、先にサブスクリプションを削除しないとトピックを削除できないことがあります。
今回作成した pubsub-cloud-run-invoker@${PROJECT_ID}.iam.gserviceaccount.com
が他で使われていないのであれば、削除しても構いません。
gcloud iam service-accounts delete pubsub-cloud-run-invoker@${PROJECT_ID}.iam.gserviceaccount.com \
--project=${PROJECT_ID} \
--quiet
注意: デフォルトのサービスアカウント(例: Compute Engine default service account や Cloud Build service account)は、プロジェクトの他の機能に影響を与える可能性があるため、むやみに削除しないようにしてください。
Cloud Runサービスをソースからデプロイすると、コンテナイメージがArtifact Registry(またはContainer Registry)に保存されます。これらはストレージ料金がかかります。数が少なければ影響は小さいですが、完全にクリーンアップしたい場合は削除できます。
これは少し手間がかかることがあります。Google Cloud ConsoleのArtifact Registryのページから手動で削除するか、gcloud artifacts docker images delete
コマンドを使用します。
例えば、publisher-app
のイメージを削除する場合 (リポジトリ名が cloud-run-source-deploy
で、イメージ名が publisher-app
の場合):
# イメージのリストを確認 (リージョンやリポジトリ名は適宜変更)
# gcloud artifacts docker images list asia-northeast1-docker.pkg.dev/${PROJECT_ID}/cloud-run-source-deploy --filter="package=publisher-app"
# イメージを削除 (TAGまたはDIGESTを指定)
# gcloud artifacts docker images delete asia-northeast1-docker.pkg.dev/${PROJECT_ID}/cloud-run-source-deploy/publisher-app:TAG_OR_DIGEST --delete-tags --quiet
まずは主要なリソース(Cloud Run, Pub/Sub)の削除で十分な場合が多いです。
もしプロジェクト をこの学習やテストのためだけに作成し、他に重要なリソースが含まれていないのであれば、プロジェクト全体を削除するのが最も簡単かつ確実に全ての関連リソースと料金発生を止める方法です。
gcloud projects delete ${PROJECT_ID} --quiet
警告: プロジェクトを削除すると、その中のすべてのリソースが削除され、元に戻すことは非常に困難(または不可能)です。十分に注意して実行してください。
おすすめの対応:
まずは 1〜3 のCloud Runサービス、Pub/Subサブスクリプション、Pub/Subトピックを削除することで、主要な能動的なコストはほぼ発生しなくなるはずです。 サービスアカウントやコンテナイメージは、必要に応じて、またはより完全にクリーンアップしたい場合に削除を検討してください。
プロジェクト全体の削除は、そのプロジェクトが本当に不要な場合にのみ行ってください。