Google PCD: API 设计、集成与事件驱动开发 — 学习指南
属于 Google Professional Cloud Developer — 学习指南. 使用经过验证的答案练习: Google 考试中心, 或参加限时模拟考试: ExamRoll.io.
概览
在 Google Cloud 上的现代应用集成,融合了精心设计的同步 API 与高弹性的异步和事件驱动模式。其目标是提供清晰的契约、强身份认证、一致的错误处理和运维控制,即使在故障、扩缩容或变更的情况下也能保持低延迟和高可用性。本节涵盖协议和 API 的选择、网关和身份验证、消息传递和事件路由、后台工作、编排、服务间的身份与信任、可靠性模式、安全 webhook 以及安全的 schema 演进。
API 设计与管理
选择合适的协议:
- REST:对人友好,可通过 HTTP 缓存,非常适合公共和合作伙伴 API。采用面向资源的设计、标准方法,仅在有价值时使用 ETag 和 HATEOAS。权衡:契约不如 protobuf 精确;可能存在数据过度获取或获取不足的问题。
- gRPC:Protobuf 契约、双向流、高效的二进制传输;非常适合低延迟的内部服务间调用。权衡:浏览器支持需要 gRPC-Web;对公共客户端的可观测性和兼容性可能更难实现。
- GraphQL:灵活的查询能力,可减少复合视图的往返次数。权衡:解析器复杂、存在 N+1 风险、缓存挑战以及访问控制的细微差别。
版本控制和分页:
- 优先选择增量、向后兼容的变更。主版本使用基于 URI 的方式(例如 /v1),次要修订通过字段和功能标志实现。弃用时应提供明确的时间表。
- 使用稳定的游标或 nextPageToken 进行分页,以避免在数据变动时出现页面不一致;对于大型数据集,避免使用偏移量(offset)。
验证和错误处理:
- REST 使用 OpenAPI 定义请求/响应 schema,gRPC 使用 protobuf 验证规则。
- 采用一致的错误模型:映射到规范的 HTTP 状态码;gRPC 使用 google.rpc.Status(包含 code、message、details)。包含机器可解析的错误原因和关联 ID。避免泄露内部实现细节。
API 管理方案选择:
- API Gateway:轻量级的托管网关,适用于 OpenAPI/gRPC 后端(Cloud Run、Cloud Functions、GKE、Compute Engine)。支持身份验证、API 密钥、JWT 验证、配额。适合无服务器和简单的控制平面。
- Cloud Endpoints (ESPv2):与您的服务一同部署;支持 OpenAPI 或 gRPC 转码、身份验证、配额和指标。适合将代理与工作负载部署在一起的场景。
- Apigee:全生命周期的 API 管理平台,提供高级策略(峰值抑制、配额、中介、转换、OAuth 提供商、变现、开发者门户)。最适合复杂的合作伙伴生态系统和南北向流量控制。
身份验证和配额:
- 对于最终用户:使用 OAuth 2.0 或 Firebase Authentication;对于服务:使用 Google 签名的 ID 令牌(OIDC)或 OAuth 服务账号令牌(双向)。
- 在靠近客户端的位置(如 Apigee)强制执行配额和峰值抑制,并针对每个消费者(通过 API 密钥或客户端凭据)进行限制,以保护后端服务。
使用 Cloud Run 后端和 OIDC 的最简 API Gateway OpenAPI 示例:
openapi: 3.0.0
info: {title: orders, version: 1.0.0}
paths:
/v1/orders:
get:
security: [{firebase: []}]
x-google-backend: {address: https://orders-xyz-uc.a.run.app}
responses: {"200": {description: OK}}
components:
securitySchemes:
firebase:
type: http
scheme: bearer
bearerFormat: JWT
x-google-issuer: https://securetoken.google.com/PROJECT_ID
x-google-audiences: PROJECT_ID
异步消息与事件处理
Pub/Sub 基础知识:
- 主题(Topic)和订阅(Subscription)解耦了发布者和消费者。交付保证为至少一次(at-least-once);可能会出现重复和乱序。
- 当处理时间较长时,使用确认(acknowledgment)并延长确认截止时间(ack deadline);应用客户端流控以避免内存压力。
- 排序:启用消息排序并提供排序键(ordering key),以保证每个键内的消息按序交付;尽可能为每个键保持单一的活跃发布者。
- 死信:配置死信主题以容纳毒丸消息(poison message)并防止无限重试;对其进行监控和分类处理。
创建主题、订阅和 DLQ:
gcloud pubsub topics create orders
gcloud pubsub topics create orders-dlq
gcloud pubsub subscriptions create orders-sub \
--topic=orders \
--dead-letter-topic=orders-dlq \
--max-delivery-attempts=5 \
--ack-deadline=30
消费者逻辑:实现幂等处理程序和去重机制(例如,通过 messageId 或应用层面的幂等键);对瞬时错误使用退避策略进行重试;将无法恢复的消息移至 DLQ 并发出警报。
Eventarc 和 CloudEvents:
- Eventarc 将来自 Google Cloud 服务、自定义来源和 Audit Logs 的事件路由到 Cloud Run、Cloud Functions 或 GKE。事件使用 CloudEvents 信封格式(包含 id、source、type、subject、time)。
- 在触发器层面按属性(如 type、subject、location)进行过滤,以减少干扰和成本。使用专用服务账号以遵循最小权限原则。
为 Cloud Storage 对象最终完成事件创建 Eventarc 触发器:
gcloud eventarc triggers create index-new-objects \
--destination-run-service=media-indexer \
--destination-run-region=us-central1 \
--event-filters="type=google.cloud.storage.object.v1.finalized" \
--event-filters="bucket=my-assets-bucket" \
--service-account=eventarc-router@PROJECT_ID.iam.gserviceaccount.com
权衡:
- Pub/Sub 针对拉取(pull)模式进行了优化,对高吞吐量具有高弹性;Eventarc 简化了从您无法控制的生产者到服务的事件路由,并使用推送(push)模式和标准化的元数据。
- 对于严格排序或严格的成本上限,考虑在发布者端进行分区和速率限制;对于极低延迟的扇出(fan-out)场景,需仔细调整订阅者的并发度。
编排、后台工作与长时运行进程
Cloud Tasks:
- 用于可靠执行后台 HTTP 调用的推送队列。设置每个队列的分派速率和并发数以保护后端。配置指数退避重试策略和最大尝试次数。
- 通过确定性的任务名称或 Idempotency-Key 标头来确保幂等性,并在服务器端进行去重。快速响应(2xx),并在需要时异步执行繁重工作。
创建具有速率限制和重试策略的队列:
gcloud tasks queues create payments-queue \
--max-dispatches-per-second=50 \
--max-concurrent-dispatches=200 \
--max-attempts=10 \
--min-backoff=5s \
--max-backoff=300s
Workflows:
- 跨 HTTP 和 Google Cloud 连接器编排多步骤业务流程。为部分失败的场景设计补偿操作(Saga 模式);避免分布式事务。
- 使用步骤级别的超时和重试策略;在重试之间持久化状态,以便在服务中断后可以恢复执行。轮询长时间运行的操作,并在截止时间到达时取消。
补偿操作示意:
main:
params: [orderId]
steps:
- charge:
call: http.post
args: {url: ${paymentsUrl}/charge, auth: {type: OIDC}, body: {orderId: ${orderId}}}
result: chargeRes
- reserveInventory:
try:
steps:
- reserve:
call: http.post
args: {url: ${inventoryUrl}/reserve, auth: {type: OIDC}, body: {orderId: ${orderId}}}
except:
as: e
steps:
- refund:
call: http.post
args: {url: ${paymentsUrl}/refund, auth: {type: OIDC}, body: {paymentId: ${chargeRes.body.id}}}
- raise: ${e}
运维指南:
- 对于需要精确速率控制的“即发即忘”式后台 HTTP 调用,优先选择 Cloud Tasks。对于扇出和多消费者的场景,使用 Pub/Sub。当您必须协调多个具有分支逻辑和补偿操作的调用时,使用 Workflows。
身份、可靠性与集成
服务到服务的身份认证与令牌传播:
- Cloud Run/Functions/Compute Engine/GKE 的工作负载应使用具有最低权限的服务账号。在 GKE 上,使用 Workload Identity 来避免节点级别的凭证。
- 对于 Cloud Run 到 Cloud Run 的调用,应使用 ID 令牌,其 audience 需与目标 URL 匹配。仅当下游服务必须代表调用者执行操作时才传播身份;否则应使用被调用者自身的服务账号。
在 Cloud Run 中获取 ID 令牌:
AUD="https://inventory-xyz-uc.a.run.app"
TOKEN=$(curl -s -H "Metadata-Flavor: Google" \
"http://metadata/computeMetadata/v1/instance/service-accounts/default/identity?audience=${AUD}")
curl -H "Authorization: Bearer ${TOKEN}" "${AUD}/v1/check"
同步依赖与弹性:
- 将客户端超时设置得低于上游超时;为每一跳分配预算。仅对幂等操作使用带抖动的截断指数退避策略进行重试。通过限制总重试时间来避免重试风暴。
- 当上游服务不健康时,使用断路器来快速失败;在 GKE/Apigee/Envoy 中,你可以配置最大挂起请求数、失败时驱逐以及健康探测。提供合理的后备方案或优雅降级。
- 将瞬时错误(429、408、500–503)映射为可重试行为;将 4xx(408/429 除外)视为不可重试。
Webhook 与第三方集成:
- 使用带有共享密钥的 HMAC 签名头或签名的 JWT 来验证入站请求;为获得更高保障,可使用 mTLS。将密钥存储在 Secret Manager 中并定期轮换。
- 快速确认请求;将任务加入 Cloud Tasks 队列或发布到 Pub/Sub 以解耦繁重的处理。对入站 IP 或密钥进行速率限制以保护后端。
- 出站 Webhook:包含一个 Idempotency-Key 以允许安全重试,并验证远程 TLS 证书和主机名。
Schema 演进与兼容性:
- REST/JSON:增加字段是安全的;绝不重用或更改现有字段的类型/含义。标记已弃用的字段并在一段时间内继续提供服务。
- Protobuf/gRPC:绝不重用字段编号;使用 reserved 标签;优先使用 optional 字段;默认值和字段存在性语义对兼容性至关重要。
- 事件:包含一个 dataVersion 并保持 CloudEvents 属性稳定;为扩展保留空间。对于 Pub/Sub,可考虑使用 Pub/Sub Schema (Avro/Protobuf) 在发布时进行验证。
- 测试:使用消费者驱动的契约测试、模拟器(Pub/Sub、Datastore/Firestore)或隔离的项目,以及金丝雀发布。在 CI 中使用临时环境和真实的配额运行集成测试,以暴露潜在的故障。
整个技术栈的安全与配额:
- 在边缘(API Gateway/Apigee/Endpoints)和在服务层强制执行身份验证。应用每个消费者的配额和峰值抑制。监控 401/403 峰值和 429 速率,以调整客户端的退避策略和配额。
- 在所有组件中记录请求 ID,并传播追踪头(Traceparent 或 X-Cloud-Trace-Context),以实现端到端的可观测性。
实际问题场景
AcmeRetail 正在 Google Cloud 上构建一个“线上购物、线下提货”服务。一个 React Web 应用调用公共 API 来下单;后端服务必须预留库存、处理支付并通知门店。团队需要低延迟的 API、可靠的后台处理、事件驱动的更新以及在部分失败时的安全回滚。
方法:
- 通过 API Gateway 在 Cloud Run 订单服务前暴露一个公共 REST API。
- 理由:对于浏览器来说,使用 JSON 的 REST 很简单;API Gateway 可以验证来自 Firebase Auth 的 JWT,对每个客户端强制执行 API 密钥和配额,并在边缘终止 TLS。Cloud Run 能随流量高峰自动扩缩。
- 对于内部热点路径(订单到库存、定价),使用 gRPC 实现服务到服务的调用。
- 理由:gRPC 减少了序列化开销并提供了严格的契约。在服务之间使用 Workload Identity (GKE) 或服务账号 (Cloud Run) 以及 OIDC。对于幂等的读取操作,超时设置为 300 毫秒,并带有两次重试和抖动。
- 使用 Workflows 来编排订单的 saga 流程:处理支付、预留库存、创建提货任务;在失败时进行补偿。
- 理由:集中式编排可以管理长时间运行的步骤和补偿操作。如果预留库存失败,Workflows 会触发退款并向客户端返回 409。
- 将领域事件发布到 Pub/Sub 的 orders 和 inventory 主题,供下游消费者(分析系统、门店通知)使用。
- 理由:实现扇出(Fanout)而无需紧密耦合。订阅者通过 orderId 作为键来实现幂等性。订阅配置了死信主题,最大交付尝试次数为 10 次,并在 DLQ 增长时触发警报。
- 当 Cloud Storage 和 Firestore 发生相关更改时,通过 Eventarc 触发事件,发送到一个 Cloud Run 通知服务。
- 理由:Eventarc 使用属性过滤器仅路由所需的事件;CloudEvents 确保了元数据的一致性。通知服务使用 Cloud Tasks 向第三方短信/邮件提供商发送通知,以控制速率和重试。
- 使用一个专用的 Cloud Run 端点处理支付提供商的 Webhook,该端点前置 API Gateway,用于验证 HMAC 签名,并使用 Cloud Tasks 进行处理。
- 理由:快速返回 200 确认可以减少提供商的重试;Tasks 确保了带退避策略的重试。密钥存储在 Secret Manager 中;请求体根据 OpenAPI schema 进行验证。
- 强制执行可靠性模式:在 Apigee 或 Envoy 中为对支付提供商的出站调用设置断路器;客户端超时设置低于提供商的 SLA;对 429/5xx 错误使用截断指数退避进行重试。
- 理由:防止级联故障和重试风暴,遵守第三方限制,并将瞬时过载转化为优雅降级。
- 采用 Schema 演进控制:内部 gRPC 使用带有 reserved 字段的 Protobuf;REST 响应使用增量式 JSON 变更;Pub/Sub 在发布时使用 Protobuf schema 验证。
- 理由:保持消费者的兼容性。契约测试和集成测试在每次合并时于 Cloud Build 中运行;金丝雀部署可以安全地验证真实流量。
- 观测与运维:在 API Gateway 和服务之间传播追踪头;导出 Cloud Logging 指标以监控错误率和 DLQ 大小;针对 SLO 消耗和 429/5xx 异常设置警报。
- 理由:快速检测回归、配额问题或提供商事件;SRE 可以快速调整配额和退避策略。
← 计算、容器和 Serverless 运行时平台 · 所有领域 · 应用数据、状态和存储模式 →
练习这些题目 → · 在 ExamRoll.io 上限时练习 →
Pass the whole exam — not just this question
You found this answer. Get every verified question and explanation in one place, and save hours of prep. Free to start.
通过考试 →