Pub/Sub:消费、重试与死信
验证:未记录
- 适用版本
- 未记录
- 验证范围
- 尚未登记验证记录。
发布业务事件;独立下游各建 Subscription,同一组 worker 共用 Subscription。
推荐做法#
- 以业务 event ID 幂等,持久化成功后 ACK;失败交给受控重试。
- 为 dead-letter forwarding 配置 Pub/Sub service agent 权限,并安排重放处理。
- 监控 backlog、最老未 ACK 消息年龄和死信积压。
常用操作#
替换为实际资源;本段不依赖 lab.env。
PROJECT_ID='REPLACE_PROJECT_ID'
SUBSCRIPTION='REPLACE_SUBSCRIPTION'
gcloud pubsub subscriptions describe "$SUBSCRIPTION" --project="$PROJECT_ID"
gcloud pubsub subscriptions get-iam-policy "$SUBSCRIPTION" --project="$PROJECT_ID"容易踩的坑#
默认 at-least-once,不保证顺序;exactly-once 也不代替业务幂等。 它只支持 Pull / StreamingPull,保证限定于同一 Region 的订阅消费;Push 不支持,重复发布仍可能形成不同消息。
- 死信尝试次数是尽力而为;消息转入死信不等于业务完成。
配置说明与完整示例(按需展开)
前置:环境篇。本篇用 Pull subscription 验证消费、ACK 和 dead-letter forwarding。
先确定消费模型#
| 需要什么 | 配置方式 |
|---|---|
| 多个 worker 分担一份处理进度 | 共同消费一个 Subscription;消息仍可能重投 |
| 订单同时送给库存、邮件等独立系统 | 每个系统建立自己的 Subscription,各自 ACK |
| 消费端主动取消息 | Pull / StreamingPull,本篇使用 CLI Pull |
| 将消息送到 HTTP 服务 | Push;处理完成后以成功响应 ACK,见 订单项目 |
默认是 at-least-once,且不保证顺序。Ordering 需在订阅启用,同 ordering key 的消息从同一 Region 发布;它不保证不同 key 之间的顺序。Exactly-once 需订阅显式启用,只支持 Pull / StreamingPull;subscriber 应连接同一 Region,跨 Region 消费仍可能重复。重新 publish 同一业务事件也可能产生新 message ID,因此仍需业务幂等。Subscription 模型、exactly-once 边界
发布、读取与 ACK#
source lab.env
gcloud services enable pubsub.googleapis.com
gcloud pubsub topics create lab-events
gcloud pubsub subscriptions create lab-worker --topic=lab-events --ack-deadline=20
gcloud pubsub topics publish lab-events --message='{"event_id":"demo-001","action":"created"}'
gcloud pubsub subscriptions pull lab-worker --limit=1 --format=json第一次故意不 ACK;超过 ack deadline 后重复 pull,直到看到重投。然后:
gcloud pubsub subscriptions pull lab-worker --limit=1 --auto-ack验收:未 ACK 的消息可重投;ACK 表示本次消费完成。默认 at-least-once 仍可能重复投递,不能用一次 ACK 证明业务只执行一次。CLI Pull 返回空时稍后重试,并检查积压指标。
死信配置#
gcloud pubsub topics create lab-dead
gcloud pubsub subscriptions create lab-dead-inspect --topic=lab-dead
gcloud beta services identity create --service=pubsub.googleapis.com --project="$PROJECT_ID"
export PROJECT_NUMBER=$(gcloud projects describe "$PROJECT_ID" --format='value(projectNumber)')
export PUBSUB_AGENT="service-${PROJECT_NUMBER}@gcp-sa-pubsub.iam.gserviceaccount.com"
gcloud pubsub topics add-iam-policy-binding lab-dead --member="serviceAccount:$PUBSUB_AGENT" --role=roles/pubsub.publisher
gcloud pubsub subscriptions add-iam-policy-binding lab-worker --member="serviceAccount:$PUBSUB_AGENT" --role=roles/pubsub.subscriber
gcloud pubsub subscriptions update lab-worker --dead-letter-topic="projects/$PROJECT_ID/topics/lab-dead" --max-delivery-attempts=5这里给 Pub/Sub service agent 的 Publisher 用于转发到 dead-letter topic,Subscriber 用于处理原 Subscription 的消息;它不是业务消费者身份。
再发布消息,持续 pull 且不 ACK,等待重投和转发;从 lab-dead-inspect 拉取死信。尝试次数是尽力而为,不能依赖精确第五次进入死信。死信
应用必须按业务 event ID 幂等。push 的成功 HTTP 响应代表 ACK,应在持久化完成后返回;不要先 ACK 再处理。Cloud Run push
转入 dead-letter topic 不等于业务已完成。修复原因后由受控流程取出原事件并重放,沿用业务 event ID;监控原订阅积压、最老未 ACK 消息年龄和死信积压。
清理#
gcloud pubsub subscriptions delete lab-worker lab-dead-inspect
gcloud pubsub topics delete lab-events lab-dead