3. EventBridge事件生产与消费

在事件驱动架构中,EventBridge 扮演的是“事件总线”的角色:生产者把事件投递到总线,消费者通过规则订阅并接收事件。要让这条链路稳定运行,核心不在于“发一条消息”,而在于事件的结构是否规范、Schema 是否可发现、版本是否可管理。本节围绕 PutEvents API、事件结构、Schema Registry 与事件版本管理四个关键点展开。

一、PutEvents API:事件进入总线的唯一入口

生产者向 EventBridge 投递事件,使用的是 PutEvents API。它支持一次批量提交最多 10 条事件,每条事件独立计费、独立返回结果。调用时需要指定目标事件总线名称(EventBusName),以及每条事件的 Source、DetailType、Detail 等字段。

aws events put-events --entries '[
  {
    "Source": "com.shop.order",
    "DetailType": "OrderCreated",
    "Detail": "{\"orderId\":\"A1001\",\"amount\":199.00,\"currency\":\"CNY\"}",
    "EventBusName": "default",
    "Time": "2025-03-01T10:00:00Z"
  }
]'

返回结果中,FailedEntryCount 为 0 表示全部成功;若大于 0,则 Entries 数组中对应位置会给出 ErrorCode 与 ErrorMessage。常见错误包括 ThrottlingException(超过 10000 条/秒的软限制)、InternalFailure(服务端临时故障)以及 ValidationException(Detail 不是合法 JSON)。生产端必须对失败条目做重试或落盘补偿,不能假设一次调用必然成功。

PutEvents 是异步接口,返回成功只代表事件已进入总线,不代表消费者已处理。端到端可靠性需要消费者侧配合幂等与死信队列。

二、事件结构:Source、DetailType 与 Detail 的三层约定

EventBridge 事件由一组固定字段和业务字段组成。固定字段包括 id、source、account、time、region、resources、detail-type、detail。其中真正决定“谁发的、发的是什么、内容是什么”的是三个字段:

  • source:事件来源标识,通常采用反向域名,如 com.shop.order,用于规则匹配。
  • detail-type:事件类型名,如 OrderCreated,同一 source 下可有多种类型。
  • detail:业务负载,必须是合法 JSON 对象,字段结构由生产者与消费者共同约定。

规则匹配时,EventBridge 使用事件模式(EventPattern)对 source、detail-type 以及 detail 内部字段做过滤。例如只接收金额大于 100 的订单事件:

{
  "source": ["com.shop.order"],
  "detail-type": ["OrderCreated"],
  "detail": {
    "amount": [{ "numeric": [">", 100] }]
  }
}

这里的关键是:detail 的字段名和类型一旦被规则引用,就变成了对外契约。随意改名或改类型,会导致规则静默不匹配,事件被丢弃而不报错,这是生产环境最常见的隐性故障。

三、Schema Registry:让事件结构可发现、可校验

Schema Registry 是 EventBridge 提供的 schema 发现与版本管理能力。开启后发现功能后,EventBridge 会从总线上的事件中自动推断出 schema,并按 source + detail-type 归类。每个 schema 是一个 JSON Schema,描述 detail 中每个字段的名称、类型、是否必填。

Schema Registry 的价值有三点:一是消费者可以查询 schema 来生成代码或校验入参;二是当生产者变更字段时,Registry 会生成新版本,便于对比差异;三是可以配合代码生成工具,把 schema 导出为 Java、TypeScript 等语言的模型类。查询某个 schema 的版本列表:

aws schemas list-schema-versions \
  --registry-name discovered-schemas \
  --schema-name com.shop.order@OrderCreated

需要注意,自动发现的 schema 是“从已发生事件推断”的结果,它反映的是历史,不是约束。若生产者发送了不符合预期的事件,Registry 不会拦截,只会记录。因此 schema 更适合作为契约文档和变更检测手段,而不是强校验网关。

四、事件版本管理:兼容性优先的演进策略

事件结构会随业务演进。版本管理要解决的核心问题是:新版本发布后,老消费者是否还能继续工作。推荐做法是“向后兼容优先”:新增字段默认可选,不删除、不改名、不改类型。若必须做破坏性变更,则通过 detail-type 增加版本后缀,例如 OrderCreatedV2,让新旧消费者并行订阅,逐步迁移。

下面这张图展示了从生产者调用 PutEvents,到事件结构、Schema 发现、版本演进,再到消费者按规则消费的完整关系。

EventBridge 事件生产与消费链路 生产者 PutEvents API 批量 ≤ 10 条 / 次 事件结构 source: com.shop.order detail-type: OrderCreated detail: { orderId, amount } 事件总线 default / 自定义 规则匹配 消费者 Lambda / SQS / SNS 按 EventPattern 订阅 Schema Registry 自动发现 detail 结构 按 source@detail-type 归类 生成 JSON Schema 版本 事件版本管理 兼容变更:新增可选字段,不改名/类型 破坏变更:OrderCreatedV2 并行发布 新旧消费者逐步迁移,避免静默丢事件 关键判断依据 • PutEvents 返回 FailedEntryCount > 0 → 按 ErrorCode 重试或落盘补偿 • 规则引用 detail 字段 → 字段名/类型即契约,变更前先查 Schema Registry 版本差异 • 破坏性变更 → 用 detail-type 版本后缀并行发布,观察新旧消费者消费量后再下线旧版本

五、生产与消费的协同要点

把四个环节串起来看,生产端要保证三件事:事件字段符合约定、PutEvents 失败可感知、schema 变更可追溯。消费端要保证两件事:规则匹配条件与 schema 一致、对重复事件做幂等处理。EventBridge 至少投递一次,重复是常态而非异常。

一个可落地的做法是:在 CI 流程中导出 Schema Registry 的 schema,与代码仓库中的事件模型做 diff,一旦发现字段被删除或类型变更就阻断发布。这样把“事件契约”从口头约定变成可检查的工程约束,版本管理才真正落地。

不要依赖自动发现的 schema 做运行时强校验。它只记录历史事件结构,不会拒绝不符合预期的事件。真正的校验应放在生产者发布前和消费者处理入口。

总结来说,PutEvents 负责把事件送进总线,事件结构定义了 source、detail-type、detail 三层契约,Schema Registry 让结构可发现、可对比,版本管理则保证结构演进时不破坏已有消费者。四者配合,事件驱动链路才能既灵活又可控。