3. Pub/Sub主题与订阅工程
在事件驱动架构中,Pub/Sub 承担的是“事件总线”的角色:生产者把消息发布到主题(Topic),消费者通过订阅(Subscription)接收消息。主题与订阅的工程化配置,直接决定了消息能否被可靠投递、失败后能否重试、异常消息如何隔离,以及谁能发布、谁能消费。本节围绕主题创建、订阅类型、消息保留、死信队列、重试策略与 IAM 权限六个关键点展开。
一、主题创建:命名、区域与发布入口
主题是消息的发布入口,本身不保存消息,消息的持久化由订阅承担。创建主题时通常关注三件事:命名规范、消息保留策略、以及是否启用消息存储策略。命名建议采用“业务域-事件类型-环境”的形式,例如 order-created-prod,便于权限与监控按前缀管理。
gcloud pubsub topics create order-created-prod \
--message-retention-duration=7d \
--project=my-event-project
其中 --message-retention-duration 控制主题在无订阅时对消息的保留时长,默认 7 天,最长 31 天。若主题下没有任何订阅,消息会在保留期后丢弃,因此生产环境应确保主题创建后立即绑定订阅。
二、订阅类型:拉取、推送与 BigQuery 订阅
订阅决定消息如何被消费。常见类型包括:
- 拉取订阅(Pull):消费者主动调用 Pull 或 StreamingPull 拉取消息,适合自建服务、需要精确控制消费速率的场景。
- 推送订阅(Push):Pub/Sub 主动将消息 POST 到 HTTPS 端点,适合 Cloud Run、Cloud Functions 等无服务器服务,端点需返回 2xx 表示成功。
- BigQuery 订阅:消息直接写入 BigQuery 表,适合日志、审计类事件的无代码落库。
选择订阅类型时,核心判断是“谁发起请求”。拉取由消费者发起,推送由 Pub/Sub 发起。推送订阅必须配置端点 URL 与认证方式,通常使用 OIDC Token 让端点验证请求来源。
三、消息保留与确认截止时间
订阅上的 消息保留时长(message retention duration) 决定消息在确认前可被重新投递的时间窗口,默认 7 天,最长 31 天。与之相关的是 确认截止时间(ack deadline),默认 10 秒,最长 600 秒。消费者必须在截止时间前调用 ack,否则消息会被重新投递。
如果处理逻辑耗时较长,应适当延长 ack deadline,或使用 modifyAckDeadline 动态续期。保留时长与 ack deadline 的关系是:ack deadline 控制单次投递的确认窗口,保留时长控制消息在订阅中可被重投的总时长。
四、死信队列与重试策略
当消息反复处理失败时,若无限重试会阻塞订阅、消耗资源。死信队列(Dead Letter Queue, DLQ)用于隔离这些“毒消息”。配置 DLQ 需要:一个死信主题、一个死信订阅,以及在原订阅上设置 --dead-letter-topic 和 --max-delivery-attempts。
gcloud pubsub subscriptions create order-created-sub \
--topic=order-created-prod \
--ack-deadline=60 \
--message-retention-duration=7d \
--dead-letter-topic=order-created-dlq \
--max-delivery-attempts=5 \
--min-retry-delay=10s \
--max-retry-delay=600s
上述配置表示:消息最多投递 5 次,重试间隔从 10 秒指数退避到最长 600 秒,超过 5 次后进入死信主题。重试策略还包括 --retry-policy,可选择 exponential-backoff 或 immediate。指数退避适合下游临时故障,立即重试适合快速失败场景。
五、IAM 权限配置
Pub/Sub 的权限模型围绕主题与订阅分别授权。常见角色包括:
| 角色 | 作用范围 | 典型用途 |
|---|---|---|
| roles/pubsub.publisher | 主题 | 生产者发布消息 |
| roles/pubsub.subscriber | 订阅 | 消费者拉取/确认消息 |
| roles/pubsub.viewer | 项目/主题 | 查看主题与订阅元数据 |
| roles/pubsub.editor | 项目 | 管理主题与订阅 |
最小权限原则要求:生产者只授予 publisher,消费者只授予 subscriber,避免直接使用 editor。推送订阅还需为 Pub/Sub 服务账号授予 iam.serviceAccountTokenCreator,以便生成 OIDC Token。
gcloud pubsub topics add-iam-policy-binding order-created-prod \
--member="serviceAccount:producer@my-event-project.iam.gserviceaccount.com" \
--role="roles/pubsub.publisher"
gcloud pubsub subscriptions add-iam-policy-binding order-created-sub \
--member="serviceAccount:consumer@my-event-project.iam.gserviceaccount.com" \
--role="roles/pubsub.subscriber"
六、整体关系与配置检查
下图把主题、订阅、死信队列、重试策略与 IAM 权限放在同一张关系图中,帮助理解各组件之间的连接方向与权限边界。
配置完成后,建议按以下顺序验证:先用 gcloud pubsub topics list 确认主题存在;再用 gcloud pubsub subscriptions describe 检查 ack deadline、保留时长、死信主题与最大投递次数;最后用一条测试消息走通“发布→消费→确认”链路,并故意让消费者返回失败,观察消息是否在 5 次后进入死信订阅。只有这条链路完整跑通,主题与订阅的工程配置才算真正落地。