Pub/Sub 支持推送消息传送和拉取消息传送。如需大致了解拉取订阅和推送订阅以及两者的对比情况,请参阅订阅者概览。本文档介绍了推送传送。如需了解有关拉取传送的讨论,请参阅拉取订阅者指南。
如果订阅使用推送传送,Pub/Sub 服务会将消息传送到推送端点。推送端点必须是可公开访问的 HTTPS 地址。推送端点的服务器必须具有由证书授权机构签署的有效 SSL 证书。
Pub/Sub 服务会将同一 Google Cloud 地区中的消息传送至 Pub/Sub 服务存储消息所在的推送端点。Pub/Sub 服务会尽最大努力传送来自同一 Google Cloud 地区的消息。
此外,推送订阅可以配置为提供授权标头,以允许端点对请求进行身份验证。自动身份验证和授权机制可用于托管在与订阅相同的项目中的 App Engine 标准和 Cloud Functions 端点。
接收消息
当 Pub/Sub 将消息传送到推送端点时,Pub/Sub 会在 POST
请求的正文中发送消息。请求的正文是 JSON 对象,消息数据位于 message.data
字段中。消息数据采用 base64 编码。
以下示例展示了向推送端点发出的 POST
请求的正文:
{ "message": { "attributes": { "key": "value" }, "data": "SGVsbG8gQ2xvdWQgUHViL1N1YiEgSGVyZSBpcyBteSBtZXNzYWdlIQ==", "messageId": "136969346945" }, "subscription": "projects/myproject/subscriptions/mysubscription" }
如需接收来自推送订阅的消息,请使用网络钩子并处理 Pub/Sub 发送到推送端点的 POST
请求。如需详细了解如何在 App Engine 中处理这些 POST
请求,请参阅编写和响应 Pub/Sub 消息。
收到推送请求后,返回 HTTP 状态代码。要确认该消息,请返回以下状态代码之一:
102
200
201
202
204
要发送此消息的否定确认,请返回其他任何状态代码。如果您发送否定确认或确认时限到期,则 Pub/Sub 会重新发送该消息。您无法修改从推送订阅收到的个别消息的确认时限。
身份验证和授权
如果推送订阅使用身份验证,则 Pub/Sub 服务会签署 JSON Web 令牌(JWT)并在推送请求的授权标头中发送 JWT。JWT 包含声明和签名。
订阅者可以解码 JWT并验证以下内容:
- 声明准确无误。
- Pub/Sub 服务签署了声明。
如果订阅者使用防火墙,则无法接收推送请求。要接收推送请求,您必须关闭防火墙并验证 JWT。
JWT 格式
JWT 是一个 OpenIDConnect JWT,包含标头、声明集和签名三个部分。Pub/Sub 服务将 JWT 编码为具有英文句点分隔符的 base64 字符串。
例如,以下授权标头包含已编码的 JWT:
"Authorization" : "Bearer eyJhbGciOiJSUzI1NiIsImtpZCI6IjdkNjgwZDhjNzBkNDRlOTQ3MTMzY2JkNDk5ZWJjMWE2MWMzZDVh YmMiLCJ0eXAiOiJKV1QifQ.eyJhdWQiOiJodHRwczovL2V4YW1wbGUuY29tIiwiYXpwIjoiMTEzNzc0M jY0NDYzMDM4MzIxOTY0IiwiZW1haWwiOiJnYWUtZ2NwQGFwcHNwb3QuZ3NlcnZpY2VhY2NvdW50LmNvb SIsImVtYWlsX3ZlcmlmaWVkIjp0cnVlLCJleHAiOjE1NTAxODU5MzUsImlhdCI6MTU1MDE4MjMzNSwia XNzIjoiaHR0cHM6Ly9hY2NvdW50cy5nb29nbGUuY29tIiwic3ViIjoiMTEzNzc0MjY0NDYzMDM4MzIxO TY0In0.QVjyqpmadTyDZmlX2u3jWd1kJ68YkdwsRZDo-QxSPbxjug4ucLBwAs2QePrcgZ6hhkvdc4UHY 4YF3fz9g7XHULNVIzX5xh02qXEH8dK6PgGndIWcZQzjSYfgO-q-R2oo2hNM5HBBsQN4ARtGK_acG-NGG WM3CQfahbEjZPAJe_B8M7HfIu_G5jOLZCw2EUcGo8BvEwGcLWB2WqEgRM0-xt5-UPzoa3-FpSPG7DHk7 z9zRUeq6eB__ldb-2o4RciJmjVwHgnYqn3VvlX9oVKEgXpNFhKuYA-mWh5o7BCwhujSMmFoBOh6mbIXF cyf5UiVqKjpqEbqPGo_AvKvIQ9VTQ"
标头和声明集是 JSON 字符串。解码后,它们将采用以下格式:
{"alg":"RS256","kid":"7d680d8c70d44e947133cbd499ebc1a61c3d5abc","typ":"JWT"} { "aud":"https://example.com", "azp":"113774264463038321964", "email":"gae-gcp@appspot.gserviceaccount.com", "sub":"113774264463038321964", "email_verified":true, "exp":1550185935, "iat":1550182335, "iss":"https://accounts.google.com" }
附加到发送到推送端点的请求的令牌可具有最长达一个小时的生命周期。
为推送身份验证设置 Pub/Sub
订阅的身份验证配置包含以下两个参数:
- 服务帐号:与推送订阅关联的 GCP 服务帐号。 推送请求使用此服务帐号的身份。
例如,它可以是角色为
roles/run.invoker
且绑定到特定 Cloud Run(全托管式)服务的服务帐号;使用此服务帐号配置的推送订阅可以调用该 Cloud Run(全托管式)服务。 - 令牌受众群体(可选):一个不区分大小写的字符串,可供 Webhook 用于验证此特定令牌的目标受众群体。
除了配置以上字段之外,您还必须授予 Pub/Sub 为您的服务帐号创建令牌所需的权限。Pub/Sub 会为您的项目创建并保留一个特殊服务帐号:service-PROJECT_NUMBER@gcp-sa-pubsub.iam.gserviceaccount.com.
。此服务帐号需要 Service Account Token Creator 角色。如果您使用 Cloud Console 为推送身份验证设置订阅,则系统会自动授予该角色。否则,您必须向此帐号明确授予该角色。
命令行
# grant Cloud Pub/Sub the permission to create tokens PUBSUB_SERVICE_ACCOUNT="service-${PROJECT_NUMBER}@gcp-sa-pubsub.iam.gserviceaccount.com" gcloud projects add-iam-policy-binding ${PROJECT_ID} \ --member="serviceAccount:${PUBSUB_SERVICE_ACCOUNT}"\ --role='roles/iam.serviceAccountTokenCreator' # configure the subscription push identity gcloud pubsub subscriptions (create|update|modify-push-config) ${SUBSCRIPTION} \ --topic=${TOPIC} \ --push-endpoint=${PUSH_ENDPOINT_URI} \ --push-auth-service-account=${SERVICE_ACCOUNT_EMAIL} \ --push-auth-token-audience=${OPTIONAL_AUDIENCE_OVERRIDE}
控制台
转到 Pub/Sub 主题页面。
点击主题名称。
创建或更新订阅。
输入身份和(可选)受众群体。
使用推送端点执行身份验证和授权
声明
JWT 可用于验证由 Google 签名的声明(包括 email
和 aud
声明)。如需详细了解 Google 的 OAuth 2.0 API 如何用于身份验证和授权,请参阅 OpenID Connect。
可通过两种机制使声明变得有意义。首先,Pub/Sub 要求,用于将服务帐号身份与推送订阅关联的用户或服务帐号具有项目或服务帐号的 Service Account User 角色(roles/iam.serviceAccountUser
)。
其次,严格控制对用于为令牌签名的证书的访问。要创建令牌,Pub/Sub 必须使用单独的签名服务帐号身份调用内部 Google 服务。该签名服务帐号必须获得授权才能为已声明的服务帐号或此帐号所属的项目创建令牌。
您可以使用 iam.serviceAccounts.getOpenIdToken
权限或 Service Account Token Creator 角色(roles/iam.serviceAccountTokenCreator
)执行此操作。
此角色或权限可以授予任何帐号。但是,您可以使用 IAM 服务来确保 Pub/Sub 签名帐号具有此权限。具体来说,Pub/Sub 使用如下所示的服务帐号:
service-{project_number}@gcp-sa-pubsub.iam.gserviceaccount.com
{project_number}
:订阅所属的 GCP 项目。gcp-sa-pubsub
:签名服务帐号所属的 Google 拥有的项目。
验证令牌
以下示例展示了如何对发送到 App Engine 应用的推送请求进行身份验证。
协议
请求:
GET https://oauth2.googleapis.com/tokeninfo?id_token={BEARER_TOKEN}
响应:
200 OK
{ "alg": "RS256", "aud": "example.com", "azp": "104176025330667568672", "email": "{SERVICE_ACCOUNT_NAME}@{YOUR_PROJECT_NAME}.iam.gserviceaccount.com", "email_verified": "true", "exp": "1555463097", "iat": "1555459497", "iss": "https://accounts.google.com", "kid": "3782d3f0bc89008d9d2c01730f765cfb19d3b70e", "sub": "104176025330667568672", "typ": "JWT" }
Java
Node.js
Python
Go
您可以在面向网站的 Google 登录指南中找到其他有关如何验证不记名 JWT 的示例。如需详细了解 OpenID 令牌,请参阅 OpenID Connect 指南,包括有助于验证 JWT 的客户端库列表。
Cloud Run 和 App Engine
Cloud Run 和 App Engine 通过验证 Pub/Sub 生成的令牌来自动对 HTTP 调用进行身份验证。用户所需的唯一配置是向调用者帐号授予必要的 IAM 角色。例如,您可以授予或撤消用于为帐号调用特定 Cloud Run 端点的权限。如需了解详情,请参阅以下教程:
停止和恢复传送
要暂时阻止 Pub/Sub 将请求发送到推送端点,请将订阅更改为拉取。请注意,此转换可能需要几分钟才能生效。
要恢复推送传送,请再次将网址设置为有效端点。要永久停止传送,请删除订阅。
配额、限制和传送速率
推送退避算法
如果推送订阅者发送否定确认,Pub/Sub 可能会使用推送退避算法传送消息。当 Pub/Sub 使用推送退避算法时,它会停止传送 100 毫秒到 60 秒的消息,然后再次开始传送消息。
推送退避算法是一种指数退避算法,可防止推送订阅者接收无法处理的消息。Pub/Sub 停止传送消息的时间取决于推送订阅者发送的否定确认条数。
例如,如果推送订阅者每秒接收 5 条消息,并且每秒发送一条否定确认,则 Pub/Sub 大约每 500 毫秒传送一次消息。如果推送订阅者每秒发送 5 条否定确认,Pub/Sub 会每隔 30-60 秒传送一次消息。
传送速率
Pub/Sub 使用慢启动算法来调整并发推送请求的数量。推送窗口是允许的最大并发推送请求数。 推送窗口在传送成功时会增大,在传送失败时会减小。系统会从一个小窗口开始:3 x N,其中 N 是发布地区的数量。
当订阅者确认消息时,窗口大小以指数方式增加,最多为 3000 x N 条未完成消息。对于订阅者确认的消息超过 99% 且平均推送请求延迟时间少于一秒的订阅,推送窗口大小最多会增加到 30000 x 未完成的消息。
推送请求延迟时间包含以下内容:
- Pub/Sub 服务器和推送端点之间的往返网络延迟时间
- 订阅者的处理时间
接收 3000 多条未完成消息后,窗口大小会以线性方式增加,以防止推送端点接收过多消息。如果平均延迟时间超过一秒,或订阅者确认的请求少于 99%,则窗口会减少到 3000 条未完成消息的下限。
如需详细了解可用于监控推送传送的指标,请参阅监控推送订阅。