
Google Cloud Pub/Sub 是 GCP 提供的全托管消息服务,基于发布/订阅模式构建。发布者将消息发送到主题,订阅者通过订阅接收主题中的消息,两者之间完全解耦,发布者不需要知道有哪些订阅者,订阅者也不需要知道消息从哪里来。
Pub/Sub 在 GCP 消息服务体系中扮演的角色,相当于 AWS 的 SNS 和 SQS 合并为一个服务:既支持一对多的广播模式(对应 AWS SNS),又支持多个独立消费者各自维护消费进度的队列模式(对应 AWS SQS),两种模式通过同一套 Topic 和 Subscription 体系实现。
Pub/Sub 解决什么问题
直接调用下游服务的架构,上下游之间存在强耦合:下游服务宕机会导致上游调用失败,下游处理能力不足时上游必须等待,任何一个环节的故障都会在调用链上扩散。
Pub/Sub 在发布者和消费者之间引入了消息层,发布者把消息投递到主题就立即返回,不需要等待任何消费者处理完成。消费者以自己的节奏消费消息,处理能力不足时消息在订阅中积压,服务恢复后继续消费,不丢失、不阻塞上游。这个设计让系统各组件可以独立扩缩,任何一个消费者的故障不会影响其他消费者,也不会影响发布者的正常运行。
具体到实际业务场景:订单创建后发布一条消息到 Pub/Sub,库存服务、物流服务、数据分析服务分别订阅这个主题,各自独立处理,互不依赖;IoT 设备实时上报数据到 Pub/Sub,Dataflow 消费数据做实时处理,结果写入 BigQuery;应用日志发布到 Pub/Sub,多个日志处理管道独立消费,一个管道故障不影响其他管道的日志接收。
核心概念:主题、订阅与消息
主题(Topic) 是发布者发送消息的命名资源。一个主题可以接收来自多个发布者的消息,也可以有多个订阅同时关联到同一个主题。主题是全局资源,在 GCP 项目内唯一命名。
订阅(Subscription) 是消费者接收消息的命名资源,每个订阅关联到一个特定的主题。同一个主题可以有多个独立订阅,每个订阅都会独立接收主题中的所有消息——这和 AWS SQS 不同,SQS 的每条消息只能被一个消费者组消费,Pub/Sub 的每个订阅是一个独立的消费管道,互不影响。
以订单系统为例:orders-created 主题关联了三个订阅:inventory-sub(库存服务)、shipping-sub(物流服务)、analytics-sub(数据分析)。每次有新订单发布到主题,三个订阅各自收到一份完整的消息副本,独立处理,物流服务故障不影响库存服务和分析服务继续消费。
消息(Message) 由数据负载(data,Base64 编码的字节串)和可选的属性(attributes,键值对元数据)构成。消息大小上限为 10MB,小于 1KB 的消息按 1KB 计费(影响成本计算)。消息发布到主题后,Pub/Sub 保留最长 7 天(默认),超时未被确认的消息会被重新投递。
创建主题与订阅
创建主题
# 创建一个标准主题
gcloud pubsub topics create orders-created
# 创建主题时同时指定消息保留时长(默认 7 天,最长 7 天)
gcloud pubsub topics create orders-created \
–message-retention-duration=7d
创建拉取订阅
# 创建拉取订阅,关联到 orders-created 主题
gcloud pubsub subscriptions create inventory-sub \
–topic=orders-created \
–ack-deadline=60 \
–message-retention-duration=7d
–ack-deadline 是确认截止时间,消费者拉取消息后必须在这个时间内发送确认(Acknowledge),否则 Pub/Sub 认为消息未被成功处理,重新投递给该订阅的其他消费者。设置原则和 SQS 的可见性超时一致:略大于消费者处理单条消息所需的最长时间。设置过短导致重复消费,设置过长导致失败后重试延迟过大。
创建推送订阅
推送订阅(Push Subscription)让 Pub/Sub 主动将消息 POST 到指定的 HTTPS 端点,而不需要消费者主动轮询:
# 创建推送订阅,将消息推送到 Cloud Run 服务
gcloud pubsub subscriptions create shipping-push-sub \
–topic=orders-created \
–push-endpoint=https://shipping-service-xxxxxxxx.run.app/pubsub/push \
–ack-deadline=30
推送端点必须是公开可访问的 HTTPS 地址,且 SSL 证书由受信任的证书颁发机构签发。Pub/Sub 无法直接将消息推送到 VPC 内部的私有地址,如果消费者在私有 VPC 内,需要通过 Eventarc 做中转,或者使用拉取模式。
拉取 vs 推送:选择依据
两种投递方式适合不同的工作负载特性。
拉取(Pull):消费者主动向 Pub/Sub 发起请求获取消息,处理完后显式确认。消费者完全控制消费速率,适合需要流控的场景(如消费者处理能力有限,不希望被 Pub/Sub 的推送速度压垮);同时适合批量处理场景,单次请求可以拉取多条消息(最多 1000 条)批量处理,减少 API 调用次数。长时运行的后台服务、Compute Engine 上的消费者程序,通常使用拉取模式。
推送(Push):Pub/Sub 主动调用消费者的 HTTPS 端点,消息到达即触发处理。适合无服务器场景,尤其是 Cloud Run——有消息时触发函数处理,没有消息时缩容到零,不产生计算费用。适合处理时间短、并发量可控的事件驱动场景。
关于 Cloud Run 如何配置接收 Pub/Sub 推送消息的完整示例,可以参考 谷歌云 Cloud Run 完整教程中的触发器配置部分。
发布和接收消息
用 Python 发布消息
from google.cloud import pubsub_v1
import json
publisher = pubsub_v1.PublisherClient()
topic_path = publisher.topic_path(‘my-project’, ‘orders-created’)
order_data = {
‘order_id’: ‘order-001’,
‘user_id’: ‘user-123’,
‘amount’: 299.99,
‘items’: [‘item-a’, ‘item-b’]
}
# 消息 data 必须是 bytes
data = json.dumps(order_data).encode(‘utf-8’)
# 可以添加消息属性用于订阅过滤
future = publisher.publish(
topic_path,
data=data,
order_type=’express’, # 消息属性键值对
region=’asia’
)
print(f’Message published: {future.result()}’)
用 Python 拉取消息
from google.cloud import pubsub_v1
import json
subscriber = pubsub_v1.SubscriberClient()
subscription_path = subscriber.subscription_path(‘my-project’, ‘inventory-sub’)
def callback(message):
data = json.loads(message.data.decode(‘utf-8’))
print(f”Processing order: {data[‘order_id’]}”)
try:
# 处理业务逻辑
process_inventory(data)
# 处理成功,确认消息
message.ack()
except Exception as e:
print(f”Processing failed: {e}”)
# 处理失败,不确认,消息将重新投递
message.nack()
streaming_pull_future = subscriber.subscribe(
subscription_path,
callback=callback
)
with subscriber:
try:
streaming_pull_future.result(timeout=300)
except Exception:
streaming_pull_future.cancel()
message.ack() 确认消息已成功处理,Pub/Sub 不再重新投递;message.nack() 显式告知处理失败,Pub/Sub 立即重新投递(不等待确认截止时间)。
死信主题(Dead Letter Topic)
处理反复失败的消息是所有消息系统都必须解决的问题。Pub/Sub 的死信主题机制:当某条消息投递失败次数超过配置的上限(最大投递尝试次数,1–100 次),自动将消息转移到指定的死信主题,不再继续重试。
# 先创建死信主题
gcloud pubsub topics create orders-dead-letter
# 创建订阅时配置死信主题,失败 5 次后转移
gcloud pubsub subscriptions create inventory-sub \
–topic=orders-created \
–dead-letter-topic=orders-dead-letter \
–max-delivery-attempts=5
死信主题同样是一个普通 Pub/Sub 主题,可以为它创建独立的订阅,用来监控和分析失败消息。通过定期检查死信主题中的消息,可以发现消费者代码的 bug、下游依赖的异常,以及格式不符合预期的消息。死信主题的最大投递尝试次数建议设为 5,对于幂等性处理的消费者可以适当提高。
消息排序与订阅过滤
消息排序
默认情况下,Pub/Sub 不保证消息的投递顺序,同一个发布者发送的消息可能以不同顺序到达消费者。需要保证顺序时,使用排序键(Ordering Key):具有相同排序键的消息会按发布顺序投递给同一区域内的消费者。
启用排序键需要在订阅上开启排序功能,并在发布时指定排序键:
# 发布时指定排序键(同一 user_id 的消息按顺序投递)
future = publisher.publish(
topic_path,
data=data,
ordering_key=’user-123′ # 相同 ordering_key 的消息按顺序到达
)
排序键只保证同一排序键的消息有序,不同排序键的消息之间没有顺序关系。启用消息排序会带来一定的吞吐量限制,不需要严格顺序的场景不应启用。
订阅过滤
订阅过滤让每个订阅只接收满足条件的消息,按消息属性过滤:
# 只接收 order_type=express 的订单消息
gcloud pubsub subscriptions create express-order-sub \
–topic=orders-created \
–message-filter=’attributes.order_type = “express”‘
被过滤掉的消息不会投递给这个订阅,但仍然计入计费量——过滤发生在投递阶段,不影响 Pub/Sub 接收消息时的成本。这和 AWS SNS 的订阅过滤行为一致,都是先收费再过滤。
扩展订阅类型:BigQuery 和 Cloud Storage
除了标准的 Pull 和 Push 订阅,Pub/Sub 还提供两种特殊订阅类型,可以直接将消息写入 GCP 存储系统,无需编写消费者代码。
BigQuery 订阅将主题中的消息直接流式写入 BigQuery 表,Pub/Sub 负责格式转换,不需要独立的 Dataflow 作业或消费者程序。适合日志分析、事件追踪等需要实时查询消息数据的场景。关于 BigQuery 的存储计费和查询成本控制,可以参考 谷歌云 BigQuery 指南的计费说明。
Cloud Storage 订阅将消息批量写入 Cloud Storage 存储桶,按配置的时间间隔或消息大小触发写入,适合需要将消息归档存储、后续批量处理的场景。
Pub/Sub 与 AWS SQS/SNS 的主要差别
从 AWS 迁移到 GCP 时,消息服务的概念映射是最容易产生困惑的部分。
AWS 的消息服务由两个独立产品构成:SNS 负责一对多的广播推送,SQS 负责队列和消费者管理。Pub/Sub 将两者统一在一个产品内——主题(Topic)承担 SNS 的广播角色,订阅(Subscription)承担 SQS 的队列消费角色。
最大的架构差别在于消费者隔离性。SQS 的一个队列对应一个消费者群体,多个消费者竞争同一个队列里的消息。Pub/Sub 的每个订阅是完全独立的消费管道,多个订阅关联到同一个主题时,每个订阅各自独立接收全量消息,消费进度相互隔离。这个设计让扇出(Fan-out)更自然——一条消息同时被库存、物流、分析三个系统独立消费,在 Pub/Sub 中只需要三个订阅,不需要 SNS → 多个 SQS 的组合。
SQS 的消息可见性超时(Visibility Timeout)对应 Pub/Sub 的确认截止时间(ackDeadline),功能完全相同,设置原则也一致。SQS FIFO 队列对应 Pub/Sub 的排序键(Ordering Key)机制,AWS SNS 订阅过滤对应 Pub/Sub 的订阅过滤器(Message Filter)。
计费方式
Pub/Sub 按实际处理的数据量计费,不按消息条数,每月前 10 GiB 免费:
| 数据量 | 单价 |
| 前 10 GiB/月 | 免费 |
| 超出部分 | $40/TiB |
数据量的计算方式是:发布到主题的数据量(Publish Throughput)+ 从订阅投递出去的数据量(Deliver Throughput)。一条 1KB 的消息发布到主题,有 3 个订阅,计费数据量是 1KB(发布)+ 3KB(投递)= 4KB。
计费相关注意事项:
消息大小不足 1KB 时,按 1KB 计算。一条 100 字节的消息,按 1KB 计费,高频发送大量小消息时这个规则的成本影响需要提前估算。
消息属性计入数据量。每个属性的键和值都计入消息大小,属性过多会增加计费数据量,建议只附加必要的属性。
被过滤掉的消息同样计费。订阅过滤器过滤的消息,在 Pub/Sub 系统内部完成投递判断时已经产生了数据处理,仍然计入计费量。
2026 年重要变更: Pub/Sub Lite 于 2026 年 3 月 18 日正式关停,所有 Lite 业务需要迁移到标准 Pub/Sub 或 Google Cloud Managed Service for Apache Kafka。新建业务不受影响,直接使用标准 Pub/Sub 即可。
账号开通与代理充值
使用 Cloud Pub/Sub 需要有效的谷歌云账号,启用 Pub/Sub API 后即可创建主题和订阅,没有额外的配额申请流程。通过 谷歌云账号出售 渠道获取的稳定账号,可以直接用于生产环境部署,1 分钟交付,免实名免绑卡。
对于月均 GCP 消耗在 $500 以上的团队(Pub/Sub + Dataflow + BigQuery 数据管道通常超过这个量级),通过 谷歌云代理商 充值可以享受赠金返点(充值 $1000 到账 $1150,充值 $3000 到账 $3500),付款支持 USDT 和对公转账,叠加 GCP 的 CUD 折扣,年度实际成本明显低于官网直充。



