跳至主要內容
ACE 服務實戰 — 第 4/11 篇

Cloud Pub/Sub 入門:服務之間怎麼傳訊息?

內文字級

Cloud Pub/Sub 入門:服務之間怎麼傳訊息?
更新:2026-10-07

前言

假設訂單送出後,通知、庫存與分析三個服務都要接著工作。若訂單服務逐一呼叫它們,任何一個服務變慢,都可能拖住整個流程。Pub/Sub 讓訂單服務先發布訊息,再由各個訂閱者自行處理。

這篇從 Topic 和 Subscription 開始,接著看訊息重送、排序與死信主題。最後比較 Pub/Sub、Cloud Tasks 和 Eventarc 各適合哪一種需求。

Pub/Sub 傳遞語意:多個 Publishers 將 Event 寫入 Topic,Topic fan-out 到各自擁有 Independent backlog 的 Subscription A、B、C;Pull 與 Push 訂閱依 Deliver、Ack deadline、Ack 或 Retry 維護狀態,BigQuery subscription 採 Managed write;重試可能產生 duplicate,Idempotent consumer 以 deduplication key 保證 one side effect,超過 max delivery attempts 的失敗訊息進入獨立 Dead-letter topic

Topic 負責 fan-out,但 backlog、ack、retry 與 dead-letter policy 都屬於各自的 subscription;因此一個消費者變慢,不會吃掉其他訂閱的訊息。Pull/Push 的重送可能造成 duplicate,業務副作用仍要靠冪等 consumer 保護;BigQuery subscription 則由 Pub/Sub 管理寫入,不是讓你自行執行 pull worker。


Pub/Sub 核心概念

基本架構

查看流程與節點文字

箭頭表示流程方向;方括號與引號內是節點名稱,可搭配下方圖解閱讀。

flowchart LR
  P["Publisher<br/>只負責發布事件"] --> T["Topic<br/>事件頻道"]
  T --> SA["Subscription A<br/>獨立 backlog、ack、retry"]
  T --> SB["Subscription B<br/>獨立 backlog、ack、retry"]
  SA --> A["Subscriber A"]
  SB --> B["Subscriber B"]
Topic 將同一事件 fan-out 到多個 Subscription;每個訂閱各自維護積壓與交付狀態,因此其中一個消費者變慢,不會阻塞另一個消費者。

三個核心元素:

元素說明類比
Topic訊息頻道,發布者往這裡送訊息YouTube 頻道
Subscription訂閱,消費者從這裡取訊息YouTube 訂閱
Message訊息本體,含 data(bytes)和 attributes(鍵值對)影片

表格超出欄寬時,可左右捲動;鍵盤可聚焦表格後用左右方向鍵查看。

訊息規格限制

限制值
最大訊息大小10 MB
訊息保留期限7 天(預設)
最長確認期限(ack deadline)600 秒
每個 Topic 的 Subscription 上限10,000 個

表格超出欄寬時,可左右捲動;鍵盤可聚焦表格後用左右方向鍵查看。


訂閱類型

Pub/Sub 建立訂閱項目的設定畫面,傳送類型下拉可選提取、推送、寫入 BigQuery、寫入 Cloud Storage,下方還有重試政策、死信主題、僅傳送一次、訊息排序、確認期限 10 秒等選項

這是建立訂閱項目的完整表單,本節四種訂閱其實都藏在最上面那個「傳送類型」下拉裡——提取(Pull)、推送(Push)、寫入 BigQuery、寫入 Cloud Storage 挑一個而已。往下還有確認期限(預設 10 秒,最長能拉到 600 秒)、死信主題、訊息排序。留意「僅傳送一次(exactly-once)」這個開關:選「提取」時才有,換成另外三種就看不到。這項功能只支援 Pull 訂閱。

Pull Subscription(拉取訂閱)

消費者主動向 Pub/Sub 拉取訊息:

# 建立 pull subscription
gcloud pubsub subscriptions create my-sub \
  --topic=my-topic \
  --ack-deadline=60

# 拉取訊息
gcloud pubsub subscriptions pull my-sub --limit=10

# 確認訊息(ack)
gcloud pubsub subscriptions ack my-sub \
  --ack-ids=ACK_ID_1,ACK_ID_2

消費者躲在防火牆後面、處理速度忽快忽慢(批次跑),或者你就是想自己控制吃訊息的速度,那就用 Pull。

運作上你要記得一件事:消費者拉到訊息後,必須在 ack deadline 內回報「我處理完了」(ack);要是超時還沒 ack,Pub/Sub 會把這則訊息再投一次。這就是所謂的 at-least-once(至少送到一次,可能重複)——所以你的處理邏輯要能被重跑也不出錯,同一則訊息算第二次、第三次進來,結果都一樣,這個性質叫冪等(idempotent)。

如果真的不能容忍重複,Pull 訂閱可以開 Exactly-once delivery(GA),確保訊息只被處理一次,但會略微增加延遲。

Push Subscription(推送訂閱)

Pub/Sub 主動將訊息 POST 到指定 HTTPS Endpoint:

# 建立 push subscription
gcloud pubsub subscriptions create my-push-sub \
  --topic=my-topic \
  --push-endpoint=https://my-service.run.app/pubsub/push \
  --push-auth-service-account=push-auth-sa@project.iam.gserviceaccount.com \
  --ack-deadline=60

訊息格式(POST body):

{
  "message": {
    "data": "SGVsbG8gV29ybGQ=", // base64 encoded
    "attributes": { "key": "value" },
    "messageId": "2070443601311540",
    "publishTime": "2026-03-11T10:00:00Z"
  },
  "subscription": "projects/my-project/subscriptions/my-push-sub"
}

消費者回傳 200、201、202、204(或 102) 表示成功 ack;回傳其他狀態碼視為 nack,訊息會重試。

如果你的消費端是 Cloud Run、App Engine 這種無伺服器服務,懶得自己維護一個 pull loop,事件來了就觸發處理,那 Push 最省事——讓 Pub/Sub 主動把訊息 POST 給你就好。

BigQuery Subscription(直接寫入 BigQuery)

無需中間消費者,直接將訊息寫入 BigQuery 表格:

gcloud pubsub subscriptions create my-bq-sub \
  --topic=my-topic \
  --bigquery-table=my-project:my-dataset.my-table \
  --write-metadata  # 同時寫入 publish_time、subscription_name 等元數據

要求:

  • 沒啟用 topic schema/table schema 時,BigQuery 表格必須有 data 欄位(BYTES、STRING 或 JSON 型別)
  • Pub/Sub service account 需要 BigQuery Data Editor 角色

適合場景:

  • 串流分析 pipeline
  • 直接從事件建立分析報表
  • 不需要業務邏輯處理

BigQuery 訂閱(以及下面的 Storage 訂閱)屬於 export 類型,只支援 at-least-once,不支援 exactly-once,所以同一筆事件可能寫入不只一次。如果下游不能接受重複資料,就要另外設計去重或冪等處理;也可評估用 Dataflow 建立處理管線。

Cloud Storage Subscription(直接寫入 GCS)

將訊息批次寫入 Cloud Storage:

gcloud pubsub subscriptions create my-gcs-sub \
  --topic=my-topic \
  --cloud-storage-bucket=my-bucket \
  --cloud-storage-file-prefix=pubsub/ \
  --cloud-storage-max-duration=600s \
  --cloud-storage-max-bytes=10MB

適合場景:

  • 長期存檔
  • 後續批次處理,例如 Managed Service for Apache Spark(原 Dataproc)、Cloud Batch
  • Data Lake 攝取

進階特性

Ordering Keys(排序鍵)

保證相同 key 的訊息按發布順序交付:

from google.cloud import pubsub_v1

# 要用 ordering key,發布端也得先開啟訊息排序
publisher_options = pubsub_v1.types.PublisherOptions(enable_message_ordering=True)
publisher = pubsub_v1.PublisherClient(publisher_options=publisher_options)
topic_path = publisher.topic_path("my-project", "my-topic")

# 使用 ordering key,相同 user_id 的訊息按順序處理
future = publisher.publish(
    topic_path,
    data=b"Order placed",
    ordering_key="user-123"  # 相同 key 保序交付
)

注意事項:

  • Subscription 也必須啟用 ordering(--enable-message-ordering)
  • 若某訊息處理失敗,相同 key 的後續訊息會暫停,直到失敗的訊息被 nack 或超時
  • 可能影響吞吐量(相同 key 的訊息通常會交給同一個消費者依序處理)

Dead Letter Topic(死信主題)

當訊息多次交付失敗後,轉移到死信 Topic:

# 建立死信 topic
gcloud pubsub topics create dead-letter-topic

# 建立 subscription 並配置死信策略
gcloud pubsub subscriptions create my-sub \
  --topic=my-topic \
  --dead-letter-topic=dead-letter-topic \
  --max-delivery-attempts=5  # 失敗 5 次後轉移

# 給 Pub/Sub service account 必要權限
PROJECT_NUM=$(gcloud projects describe my-project --format='value(projectNumber)')
PUBSUB_SA="service-${PROJECT_NUM}@gcp-sa-pubsub.iam.gserviceaccount.com"

gcloud pubsub topics add-iam-policy-binding dead-letter-topic \
  --member="serviceAccount:${PUBSUB_SA}" \
  --role=roles/pubsub.publisher

gcloud pubsub subscriptions add-iam-policy-binding my-sub \
  --member="serviceAccount:${PUBSUB_SA}" \
  --role=roles/pubsub.subscriber

死信處理流程:

  1. 訊息交付失敗(消費者 nack 或超時)
  2. Pub/Sub 重試(依退避策略)
  3. 達到最大嘗試次數(max-delivery-attempts)
  4. 訊息轉移到死信 Topic
  5. 另一個消費者(或告警)處理死信
查看流程與節點文字

箭頭表示流程方向;方括號與引號內是節點名稱,可搭配下方圖解閱讀。

flowchart TB
  D["交付訊息給消費者"] --> OK{"在 ack deadline<br/>內成功?"}
  OK -->|"是:ack"| DONE["完成並移出 backlog"]
  OK -->|"否:nack 或逾時"| COUNT["交付嘗試次數加一"]
  COUNT --> MAX{"達到 max delivery<br/>attempts?"}
  MAX -->|"否"| WAIT["依退避策略等待"]
  WAIT --> D
  MAX -->|"是"| DLT["轉送 Dead<br/>Letter Topic"]
  DLT --> OPS["死信訂閱分析、<br/>修復或告警"]
只有成功 ack 才結束交付;一般失敗會退避後重送,達到上限才把訊息隔離到 Dead Letter Topic,避免問題訊息無限阻塞正常工作。

Exactly-Once Delivery(精確一次交付)

# 啟用精確一次交付(GA 功能)
gcloud pubsub subscriptions create my-sub \
  --topic=my-topic \
  --enable-exactly-once-delivery

代價:

  • 更高延遲(需要額外確認機制)
  • 較低吞吐量
  • 只在 Pull Subscription 支援

建議:大多數情況用 at-least-once 搭配消費者端的冪等設計就夠了,真的非用不可時再開 exactly-once。

訊息過濾(Message Filtering)

# 只接收特定 attribute 的訊息
gcloud pubsub subscriptions create filtered-sub \
  --topic=my-topic \
  --message-filter='attributes.region = "us-central1"'

事件驅動架構設計模式

查看流程與節點文字

箭頭表示流程方向;方括號與引號內是節點名稱,可搭配下方圖解閱讀。

flowchart LR
  subgraph FAN["Fan-Out:每個訂閱都收到一份"]
    FT["Order Topic"] --> FS1["通知 Subscription"] --> EMAIL["Email Service"]
    FT --> FS2["庫存 Subscription"] --> INV["Inventory Service"]
  end
  subgraph QUEUE["Task Queue:同一訂閱競爭消費"]
    QT["Image Topic"] --> QS["processing-sub"]
    QS -->|"一則只交給其中一個"| W1["Worker 1"]
    QS --> W2["Worker 2"]
  end
  subgraph ES["Event Sourcing:事件成為不可變紀錄"]
    WRITE["狀態變更"] --> ET["account-events"]
    ET --> ARCHIVE["GCS 歷史存檔"]
    ET --> ANALYTICS["BigQuery 分析"]
  end
  subgraph CQ["CQRS:寫入與查詢模型分離"]
    CMD["Write Model"] --> DOMAIN["domain-events"] --> READ["Read Model"]
    DOMAIN --> INDEX["快取/搜尋索引"]
  end
判斷關鍵在 Subscription:多個獨立 Subscription 是廣播;多個 Worker 共用一個 Subscription 則是競爭消費。Event Sourcing 與 CQRS 再利用事件建立歷史紀錄或讀取模型。

模式一:Fan-Out(廣播)

一個事件觸發多個下游服務:

實現:每個下游服務建立獨立的 Subscription,獨立接收同樣的訊息。

模式二:Task Queue(任務佇列)

多個 Worker 競爭消費訊息:

特性:一個 Subscription 中的訊息只會被一個消費者處理(競爭消費)。

模式三:事件溯源(Event Sourcing)

所有狀態變更都以事件形式記錄:

模式四:CQRS(命令查詢職責分離)

寫入操作發布事件,讀取模型訂閱事件更新:


Cloud Pub/Sub vs Cloud Tasks vs Eventarc

這三個服務都能接上事件流程,但負責的事不同。先看各自的用途:

特性Cloud Pub/SubCloud TasksEventarc
主要用途非同步訊息傳遞任務排程與重試GCP 事件路由
目標多個 Subscriber單一 WorkerCloud Run/Functions
排程執行❌✅(指定時間執行)❌
明確任務❌✅(可查詢、刪除任務)❌
保序交付✅(ordering key)❌❌
Fan-out✅❌有限
觸發來源任何應用任何應用GCP 服務事件
最大延遲無30 天近乎即時

表格超出欄寬時,可左右捲動;鍵盤可聚焦表格後用左右方向鍵查看。

選型決策:

用 Cloud Pub/Sub 當:

  • 需要一對多廣播(fan-out)
  • 需要高吞吐量的訊息串流
  • 生產者和消費者需要解耦
  • 訊息可能有多個獨立消費者

用 Cloud Tasks 當:

  • 有單一目標(一個 Worker / 一個 HTTP 端點),而不是廣播給很多人
  • 需要延遲執行或排程(e.g., 1 小時後發送 email)
  • 需要可查詢、可刪除的任務列表
  • 需要限制 Worker 的 QPS(速率控制)

Cloud Tasks 不是 exactly-once。官方明講它是 at-least-once:99.999% 以上只會跑一次,但仍有可能重複投遞,所以 handler 一樣要寫成冪等。別被「任務佇列」這個名字騙了。

用 Eventarc 當:

  • 響應 GCP 服務事件(GCS 上傳、BigQuery 完成、Pub/Sub 訊息)
  • 統一管理 GCP 事件路由到 Cloud Run
  • CloudEvent 標準格式整合
查看流程與節點文字

箭頭表示流程方向;方括號與引號內是節點名稱,可搭配下方圖解閱讀。

flowchart TB
  START{"需求從哪裡開始?"}
  START -->|"GCP 服務事件<br/>要路由到 Cloud Run/Functions"| EVENTARC["Eventarc"]
  START -->|"應用程式主動送出工作或事件"| TARGET{"需要多少個獨立消費者?"}
  TARGET -->|"多個:廣播或高吞吐串流"| PUBSUB["Cloud Pub/Sub"]
  TARGET -->|"單一 HTTP Worker"| CONTROL{"需要延遲執行、刪除任務<br/>或限制 QPS?"}
  CONTROL -->|"是"| TASKS["Cloud Tasks"]
  CONTROL -->|"否,但生產者與消費者要解耦"| PUBSUB
  PUBSUB --> IDEMP["預設 at-least-once<br/>消費者仍須冪等"]
  TASKS --> IDEMP
  EVENTARC --> CLOUD["以 CloudEvents 統一路由"]
先分辨 GCP 原生事件路由與應用程式工作,再看是否需要多個獨立消費者。Cloud Tasks 適合可控的單一目標,但它與 Pub/Sub 一樣仍可能重複投遞。

⚠️ 注意:Cloud Pub/Sub Lite 已棄用,也不再開放新客戶使用;官方現行公告的關閉日是 2027/1/31(2024 年 6 月的 release notes 最初寫的是 2026/3/18)。規劃新系統時,請改評估 Cloud Pub/Sub。

Cloud Scheduler:定時觸發的補充

先把它的定位講清楚:Cloud Scheduler 不是訊息系統,而是一個按時間戳觸發前面三者的鬧鐘——時間到了,它去敲 Pub/Sub Topic 或 HTTP 端點。所以它跟 Pub/Sub / Cloud Tasks 不是競爭關係,而是經常搭配使用:

# 每天早上 9 點(沒指定 --time-zone 時是 UTC)觸發 Pub/Sub Topic
gcloud scheduler jobs create pubsub daily-report \
  --schedule="0 9 * * *" \
  --topic=report-trigger \
  --message-body='{"type": "daily"}'

# 每 5 分鐘呼叫 Cloud Run 端點
gcloud scheduler jobs create http health-check \
  --schedule="*/5 * * * *" \
  --uri=https://my-service-xxx.run.app/cron/health \
  --http-method=POST \
  --oidc-service-account-email=scheduler-sa@my-project.iam.gserviceaccount.com
場景選擇
定時觸發(cron-like)Cloud Scheduler → Pub/Sub 或 HTTP
延遲執行(X 分鐘後)Cloud Tasks(指定 scheduleTime)
即時非同步廣播Cloud Pub/Sub

表格超出欄寬時,可左右捲動;鍵盤可聚焦表格後用左右方向鍵查看。

📝 考場提點

備考時要留意 Pub/Sub、Cloud Tasks、Eventarc 的選型,判斷全看題目埋了哪個關鍵字:

  • 「fan-out」「多個服務都要收到同一個事件」「多訂閱者」→ Cloud Pub/Sub
  • 「延遲 X 分鐘後執行」「限制 Worker 的 QPS / 速率」「指定 scheduleTime」「單一目標端點」→ Cloud Tasks
  • 「GCS 上傳檔案後觸發 Cloud Run」「某個 GCP 服務發生事件就跑」「CloudEvent」→ Eventarc

Cloud Tasks 不是 exactly-once,而是 at-least-once。即使重複派送不常見,handler 仍應設計成冪等。題目若把 Cloud Tasks 說成「保證只執行一次」,就要留意。


實戰範例:電商訂單事件系統

底下是一個完整的電商訂單事件驅動系統,從頭到尾跑一遍:

查看流程與節點文字

箭頭表示流程方向;方括號與引號內是節點名稱,可搭配下方圖解閱讀。

flowchart LR
  ORDER["訂單服務"] -->|"ORDER_PLACED<br/>ordering key = user_id"| TOPIC["order-events Topic"]
  TOPIC --> PUSH["通知 Push Subscription"] --> RUN["Cloud Run 通知服務"]
  TOPIC --> PULL["庫存 Pull Subscription"] --> WORKER["庫存 Worker 批次處理"]
  TOPIC --> BQSUB["BigQuery Subscription"] --> BQ["BigQuery 訂單分析表"]
  PUSH -. "超過重試上限" .-> DLQ["order-events-dlq"]
  PULL -. "超過重試上限" .-> DLQ
  DLQ --> ONCALL["告警與人工/自動補償"]
一個 Topic 同時服務即時通知、可控的庫存處理與分析攝取;業務訂閱失敗到上限後共用死信主題,避免錯誤訊息悄悄遺失。
# 1. 建立訂單事件 Topic
gcloud pubsub topics create order-events

# 2. 建立訂單死信 Topic
gcloud pubsub topics create order-events-dlq

# 3. 訂單通知服務(Push 訂閱 → Cloud Run)
gcloud pubsub subscriptions create order-notification-sub \
  --topic=order-events \
  --push-endpoint=https://notification-service.run.app/orders \
  --push-auth-service-account=notification-sa@project.iam.gserviceaccount.com \
  --ack-deadline=60 \
  --dead-letter-topic=order-events-dlq \
  --max-delivery-attempts=5

# 4. 庫存服務(Pull 訂閱,批次處理)
gcloud pubsub subscriptions create order-inventory-sub \
  --topic=order-events \
  --ack-deadline=120 \
  --max-delivery-attempts=5 \
  --dead-letter-topic=order-events-dlq \
  --enable-message-ordering  # 保序處理

# 5. 分析服務(BigQuery 直接訂閱)
gcloud pubsub subscriptions create order-analytics-sub \
  --topic=order-events \
  --bigquery-table=my-project:analytics.orders \
  --write-metadata

# 6. 發布訂單事件(Python)
import json
import base64
from google.cloud import pubsub_v1

publisher_options = pubsub_v1.types.PublisherOptions(enable_message_ordering=True)
publisher = pubsub_v1.PublisherClient(publisher_options=publisher_options)
topic_path = publisher.topic_path("my-project", "order-events")

order = {
    "order_id": "ORD-2026031100001",
    "user_id": "USER-123",
    "items": [{"sku": "SKU-001", "qty": 2}],
    "total": 1299.00
}

# 發布訊息(使用 ordering key 保序)
future = publisher.publish(
    topic_path,
    data=json.dumps(order).encode("utf-8"),
    ordering_key=f"user-{order['user_id']}",  # 同用戶訂單保序
    event_type="ORDER_PLACED",
    version="v1"
)
message_id = future.result()
print(f"Published message ID: {message_id}")

Pub/Sub 監控與維運

關鍵指標

# 查看 subscription 的未確認訊息數(backlog):gcloud 沒有 monitoring metrics 指令,
# 到 Cloud Monitoring 的 Metrics Explorer 查這個指標(官方建議做告警時改用 num_unacked_messages_by_region):
# pubsub.googleapis.com/subscription/num_undelivered_messages
指標說明告警建議(經驗值,依系統調整)
num_undelivered_messagesBacklog 訊息數> 1000 時告警
oldest_unacked_message_age最舊未確認訊息年齡> 300s 時告警
dead_letter_message_count轉送到死信主題的訊息數Dead letter 增加時告警

表格超出欄寬時,可左右捲動;鍵盤可聚焦表格後用左右方向鍵查看。

調整 Subscription 配置

# 修改 ack deadline
gcloud pubsub subscriptions update my-sub \
  --ack-deadline=120

# 啟用 exactly-once delivery(慎用)
gcloud pubsub subscriptions update my-sub \
  --enable-exactly-once-delivery

# 查看 subscription 詳細資訊
gcloud pubsub subscriptions describe my-sub

IAM 與安全

GCP IAM 授予存取權的角色選單,左側為基本角色 Owner/Editor/Viewer,右側為依產品分類的預先定義角色,示範最小權限的角色選取

下面那幾條 gcloud 指令裡的 --role=roles/pubsub.publisher、 roles/pubsub.subscriber,在 Console 就是從這個角色選單挑出來的。左邊那組是「基本角色」(Owner/Editor/Viewer),右邊才是依產品切細的「預先定義角色」。備考時要記得最小權限:發布者只給 pubsub.publisher、訂閱者只給 pubsub.subscriber,別圖方便丟一個 Editor 下去——真的被入侵時,攻擊者能碰的範圍差很多。

# 給發布者 Topic 發布權限
gcloud pubsub topics add-iam-policy-binding my-topic \
  --member="serviceAccount:publisher-sa@project.iam.gserviceaccount.com" \
  --role=roles/pubsub.publisher

# 給訂閱者 Subscription 訂閱權限
gcloud pubsub subscriptions add-iam-policy-binding my-sub \
  --member="serviceAccount:subscriber-sa@project.iam.gserviceaccount.com" \
  --role=roles/pubsub.subscriber

# Push 驗證:Pub/Sub service agent 要能替推送身分的 Service Account 簽發 token(Token Creator);
# 2021/4/8(含)以前建立的專案才需手動授予,之後建立的專案 service agent 已內建同等權限
gcloud iam service-accounts add-iam-policy-binding \
  push-auth-sa@project.iam.gserviceaccount.com \
  --member="serviceAccount:service-PROJECT_NUMBER@gcp-sa-pubsub.iam.gserviceaccount.com" \
  --role=roles/iam.serviceAccountTokenCreator

ACE 考試重點整理

📝 考場提點

先分清楚「多個 consumer 分工」和「每個 subscription 各收一份」:

  • 同一個 Subscription 掛多個 consumer = 競爭消費,一則訊息只會被其中一個處理(任務分流就靠這個)
  • 同一個 Topic 掛多個 Subscription = fan-out,每個 Subscription 都會收到完整一份(廣播就靠這個)

另外幾個容易混淆的限制也可以一起核對:

  • exactly-once 只支援 Pull 訂閱;Push 與 BigQuery / Storage 這些 export 訂閱都只有 at-least-once,所以處理邏輯一律要冪等
  • Pub/Sub Lite 已棄用(官方公告 2027/1/31 關閉,已不收新客戶);新系統應改評估 Cloud Pub/Sub
  • 必背數字:最大訊息 10 MB、預設保留 7 天、ack deadline 最長 600 秒、每個 Topic 上限 10,000 個 Subscription

必背知識點

  1. Pub/Sub Lite 已棄用(官方公告 2027/1/31 關閉),考試選 Cloud Pub/Sub
  2. 一個 Topic 多個 Subscription = Fan-out;一個 Subscription 多個消費者 = 競爭消費
  3. 最大訊息大小 10MB,保留 7 天
  4. Ordering Key 保證相同 key 的訊息按序交付
  5. Dead Letter Topic 需要給 Pub/Sub SA 發布權限
  6. Exactly-once delivery 是 GA 功能,但只支援 Pull Subscription
  7. BigQuery Subscription 和 Cloud Storage Subscription 都是 GA 功能——但它們是 export 類型,只有 at-least-once,沒有 exactly-once,別誤以為直寫 BQ 就保證不重複

選型題公式

場景答案
多個服務同時收到事件Cloud Pub/Sub(fan-out)
1 小時後執行任務Cloud Tasks(延遲執行)
GCS 上傳觸發 Cloud RunEventarc
限制 Worker 處理速率Cloud Tasks(rate limiting)
高吞吐量訊息串流Cloud Pub/Sub
單一目標、可排程/延遲的任務Cloud Tasks(at-least-once,handler 要冪等)

表格超出欄寬時,可左右捲動;鍵盤可聚焦表格後用左右方向鍵查看。

常見陷阱題

Q:如何讓訊息只被一個消費者處理? A:多個消費者訂閱同一個 Subscription(競爭消費)。如果訂閱不同 Subscription,每個 Subscription 都會收到同一份訊息。

Q:Pub/Sub 能保證訊息順序嗎? A:預設不保證。需要使用 Ordering Key 並在 Subscription 啟用 enable-message-ordering,才能保證相同 key 的訊息按序交付。

Q:訊息未被 ack 會怎樣? A:超過 ack deadline 後,Pub/Sub 會重新投遞該訊息(at-least-once 語義)。要避免重複處理,消費者應設計為冪等(idempotent)。

Q:如何處理持續處理失敗的訊息? A:設定 Dead Letter Topic,指定最大重試次數(max-delivery-attempts),失敗訊息自動轉移,避免阻塞正常訊息流。


總結

Pub/Sub 適合讓事件生產者和消費者分開演進。設計時先確認每個訂閱者是否都要收到一份訊息、是否需要排序,以及處理失敗後要重試多久;Dead Letter 和冪等處理也要一起規劃。

規劃新系統時,不必再把已棄用、官方公告 2027/1/31 關閉的 Pub/Sub Lite 列入選項。另一個容易混淆的點是 exactly-once delivery:它只支援 Pull 訂閱;Push 和匯出訂閱仍要考慮重複投遞。因此,不論用哪一種訂閱,都應讓訊息處理邏輯具備冪等性。

下一課 GCP-109:Cloud Run 入門,學習如何零運維部署容器化應用程式。

ACE 服務實戰 — 第 4 篇/共 11 篇 查看系列全覽 →

讀完後,留一個學習紀錄

試著用自己的話說出一個重點,以及你會如何運用。實作文章請先核對結果與清理資源,再標記為讀完。

文章進度以你確認讀完的標記為準,可隨時取消。舊版造訪紀錄保留,但不計入讀完;這份自評不代表已掌握內容。

留言討論

文章目錄與系列

徽章解鎖!