Skip to content

hirokts/pubsub-learn

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

非同期画像処理リクエストシステム(模擬)

  • ユーザーがWeb API経由で「画像処理のリクエスト」(例: サムネイル作成指示)を送信
  • そのリクエストがPub/Subに送られる
  • バックエンドでは、別のワーカーがそのリクエストをPub/Subから受け取り、画像処理を模擬的に実行

登場人物

  1. パブリッシャー (Publisher App):
    • FastAPI を使ったシンプルなWeb API。
    • ユーザーからのリクエスト(例: /request_image_processing エンドポイント)を受け付けます。
    • リクエスト内容(例: 画像ファイル名、処理の種類など)をメッセージとしてPub/Subトピックに送信します。
    • ユーザーにはすぐに「リクエストを受け付けました」と応答を返します(実際の処理完了を待たない)。
  2. サブスクライバー (Worker App):
    • こちらもFastAPIを使ったシンプルなWebアプリケーション(Pub/SubのPushサブスクリプションで受信するため)。
    • Pub/Subトピックからメッセージ(画像処理リクエスト)をPushで受信します。
    • 受信したメッセージに基づいて、画像処理を模擬的に実行します(例: ログに処理内容を出力し、数秒待機する)。
    • 処理が完了したらPub/SubにACK(確認応答)を返します。
  3. Pub/Sub:
    • パブリッシャーとサブスクライバーの間でメッセージを仲介します。

学習できること:

  • Pub/Subによる非同期処理の実現。
  • アプリケーション間の疎結合化。
  • PythonでのPub/Subライブラリの基本的な使い方(メッセージのパブリッシュ、Pushサブスクリプションでの受信)。
  • Cloud Runとの連携(オプション)。

準備

  1. Google Cloud プロジェクト:
    • プロジェクトを作成または選択します。
    • Pub/Sub API を有効にします。
    • 課金を有効にします。
  2. Python環境:
    • Python 3.7以上。
    • pip install google-cloud-pubsub flask を実行してライブラリをインストールします。
  3. 認証:
    • ローカル開発時: 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]"

1. Pub/Subトピックの作成

gcloud pubsub topics create image-processing-requests

デプロイとPushサブスクリプションの作成 (Cloud Runの場合)

  1. パブリッシャーとサブスクライバーを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 を控えておきます。
  1. 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
}

使ったリソースのクリーンアップ

  1. Cloud Run サービス (publisher-app, worker-app)
  2. Pub/Sub トピック (image-processing-requests)
  3. Pub/Sub サブスクリプション (image-processing-subscription)
  4. サービスアカウント (pubsub-cloud-run-invoker@${PROJECT_ID}.iam.gserviceaccount.com)
  5. コンテナイメージ (Artifact Registry内)
  6. Google Cloudプロジェクト全体

完全に料金を発生させないようにするには、これらのリソースを削除するのが最も確実です。


1. Cloud Run サービスの削除

これにより、サービスの実行に伴う料金が発生しなくなります。

# 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 オプションを外すと、削除前に確認を求められます。


2. Pub/Sub サブスクリプションの削除

サブスクリプションが存在すると、メッセージの滞留や配信試行に関連するわずかながらコストが発生する可能性があるため、削除します。

gcloud pubsub subscriptions delete image-processing-subscription \
    --project=${PROJECT_ID} \
    --quiet

3. Pub/Sub トピックの削除

トピック自体はメッセージが保存されていなければ通常大きなコストはかかりませんが、クリーンアップのためには削除するのが良いでしょう。

gcloud pubsub topics delete image-processing-requests \
    --project=${PROJECT_ID} \
    --quiet

注意: トピックにまだサブスクリプションが関連付けられている場合、先にサブスクリプションを削除しないとトピックを削除できないことがあります。


4. Pubsub用カスタムサービスアカウントの削除 (オプション)

今回作成した 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)は、プロジェクトの他の機能に影響を与える可能性があるため、むやみに削除しないようにしてください。


5. コンテナイメージの削除 (オプション)

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)の削除で十分な場合が多いです。


6. Google Cloud プロジェクト全体の削除 (最も包括的な方法)

もしプロジェクト をこの学習やテストのためだけに作成し、他に重要なリソースが含まれていないのであれば、プロジェクト全体を削除するのが最も簡単かつ確実に全ての関連リソースと料金発生を止める方法です。

gcloud projects delete ${PROJECT_ID} --quiet

警告: プロジェクトを削除すると、その中のすべてのリソースが削除され、元に戻すことは非常に困難(または不可能)です。十分に注意して実行してください。


おすすめの対応:

まずは 1〜3 のCloud Runサービス、Pub/Subサブスクリプション、Pub/Subトピックを削除することで、主要な能動的なコストはほぼ発生しなくなるはずです。 サービスアカウントやコンテナイメージは、必要に応じて、またはより完全にクリーンアップしたい場合に削除を検討してください。

プロジェクト全体の削除は、そのプロジェクトが本当に不要な場合にのみ行ってください。

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published