关于 amazon-eventbridge-event-bus
用于构建和管理新版 Amazon EventBridge 自定义事件总线的技能,涵盖事件发布、订阅筛选与投递、保留和重放,并区分新版 API 与经典 EventBridge。
主要功能
- 01创建和配置自定义事件总线
- 02发布 JSON 和二进制事件负载
- 03筛选并转换订阅事件
- 04保留、暂停、恢复和重放事件
- 05配置事件源与目标
- 06排查投递和授权问题
适用场景
- 01设置自定义总线和订阅者
- 02选择发布 API 及对应筛选器
- 03重放保留事件以进行恢复
- 04迁移经典 EventBridge 配置
MCP 相关
建议使用 AWS MCP 服务执行带审计日志的沙箱 CLI 调用;相关指导也适用于标准 AWS CLI。
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ aws/ agent-toolkit-for-aws --skill amazon-eventbridge-event-bus安装后在 Claude Code 中输入/amazon-eventbridge-event-bus确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/authorization.mdcloudevents.mdcode-samples.mdcost-and-quotas.mddelivery-troubleshooting.mdevent-sources.mdfilters-and-expressions.mdinfrastructure-as-code.mdmigrating-from-classic.mdobservability.mdprovisioning-and-state.mdreplay-and-recovery.mdschema-registries.mdsecurity-and-sharing.mdsetup-walkthroughs.mdtarget-configuration.mdtarget-contract.md详细介绍
使用新的 EventBridge 自定义事件总线进行构建
概述
新的 EventBridge 自定义事件总线会路由并保留事件。你可以通过两种 API 之一发布事件,订阅者则会筛选事件、按需进行转换,并将每个匹配的事件发送到一个目标。
编写任何筛选器、转换器或目标参数之前,请先阅读第 5 章和第 6 章。 两种发布 API 传递的负载形状不同,为其中一种编写的表达式用于另一种时,会无声地匹配不到任何内容。
发布指标默认开启,因此你始终可以确认事件是否到达总线。订阅者日志默认关闭,因此请在调试投递问题之前开启日志,而不是等到问题发生后再开启(第 18 章)。
最适合搭配 AWS MCP 服务使用,建议通过它在此技能中运行 CLI 调用:它会在经过沙盒隔离的环境中执行调用,并记录审计日志。所有指导也适用于标准 AWS CLI 访问方式。
约定
此技能中的关键词 MUST、MUST NOT、SHOULD 和 MAY 的含义遵循 RFC 2119 中的定义。它们仅出现在决策流程中,因为采取错误的做法会导致配置损坏或事件无声丢失。MUST 表示绝对要求,SHOULD 表示强烈建议,但你可能有具体理由不予遵循,MAY 表示确实可选。
其他内容均为一般说明。描述服务行为的句子不会带有关键词,因为它陈述的是事实,而不是对你的指示。
不适用此技能的情况
此技能仅适用于新的自定义事件总线,也就是通过 eventsv2 CLI 和 eventbridgev2 SDK 客户端访问的服务。它不涵盖:
- 经典 EventBridge,即包含规则、目标、存档以及
AWS::Events::Rule上事件模式的eventsAPI。这两项服务共用events:IAM 命名空间和部分术语,这正是它们容易混淆的原因。如果你正在编写规则,就不是在使用新的总线。如果你正在迁移,第 3 章会介绍这些概念的对应关系。 - EventBridge Pipes、Scheduler 和 Schemas(经典架构注册表及其发现功能)。它们使用不同的 API。
- 配置 Firehose 服务本身,例如缓冲提示或记录转换。Firehose 传输流是有效的订阅者目标;第 9 章介绍这方面的内容。
触发示例
- “编写一个筛选器,让此订阅者只接收金额超过 $500 的订单。”
- “我的生产者显示 PUBLISHED,但队列里什么都没有。我该检查什么?”
- “对于 Protobuf 负载,我应该使用 PutEvents 还是 PutRawEvents?”
- “设置一个订阅者,重新处理过去两天内的所有内容。”
- “编写一个 JSONata 表达式,从事件中提取客户 ID 并写入 DynamoDB 的 putItem。”
防护措施 — 此技能自身文件的位置(MCP 与本地安装)
此技能可以通过两种方式加载,它们会从不同位置解析技能自带的文件。读取参考资料前,请先确定技能的加载方式:
- 通过 AWS MCP
retrieve_skill工具加载: 此技能未安装在本地文件系统中。你必须使用retrieve_skill并通过file参数获取每份参考资料(例如file="references/setup-walkthroughs.md")。请勿在本地使用file_read读取这些路径——它们并不存在于磁盘上。 - 在本地安装(例如
.kiro/skills/amazon-eventbridge-event-bus/或~/.claude/skills/amazon-eventbridge-event-bus/):使用相对路径从本地技能目录读取文件。
此区别仅适用于技能自身打包的文件。用户数据和会话产物始终从用户的工作目录读取并写入其中。切勿通过 retrieve_skill 获取或写入客户数据。
参考文件
下表所列章节介绍了相关决策和故障模式;详细内容请参阅这些文件。任务符合某一行的描述时,请加载对应文件,默认不要全部加载。
| 文件 | 何时加载 |
|---|---|
| setup-walkthroughs.md | 在单个账户中,或通过 AWS RAM 在多个账户间共享,端到端搭建可用的总线,包括前提条件和拆除步骤 |
| code-samples.md | 编写单个 CLI 或 SDK 调用(Python、Java、TypeScript):创建总线和订阅者、使用任一 API 发布事件、二进制负载、重放、跨账户授权、等待器、单条结果、限流退避 |
| filters-and-expressions.md | 编写任何过滤模式、JSONata 表达式或读取事件的目标参数;包括两种完整的投递信封 |
| target-configuration.md | 配置任何订阅者目标,尤其是通用目标 |
| target-contract.md | 编写实际的 CreateSubscriber 调用:必填字段、每种目标类型的可用示例、字面值与 JSONata、投递错误分类 |
| migrating-from-classic.md | 从经典版 EventBridge 迁移、规划迁移顺序,或排查导致新总线配置错误的经典用法 |
| event-sources.md | 使用事件源将 AWS 服务事件或合作伙伴事件发送到总线,或排查转发的事件未到达或未匹配过滤器的问题 |
| provisioning-and-state.md | 创建或更新总线,或排查资源卡在意外状态的问题 |
| delivery-troubleshooting.md | 事件已发布但从未到达,或构建能正确统计投递次数的测试装置 |
| authorization.md | 编写 IAM 策略或总线资源策略、检查跨账户访问,或处理任何将事件转发到总线的操作 |
| replay-and-recovery.md | 读取历史事件而非新事件、暂停或恢复,或排查看似故障的重放 |
| observability.md | 设置指标、警报或托管日志投递;读取投递日志;跨账户观测 |
| schema-registries.md | 发布 Avro、Protobuf 或任何非 JSON 内容;了解接受的内容类型;与 Kafka 并行运行 |
| cloudevents.md | 发布或使用 CloudEvents,或按 CloudEvents 属性进行过滤 |
| security-and-sharing.md | 加密总线、跨账户共享或添加标签 |
| cost-and-quotas.md | 计费机制、跨账户费用分摊、优化事件以降低成本,或处理限流 |
| infrastructure-as-code.md | 编写 CloudFormation 模板、跨账户拆分堆栈,或设置私有连接 |
1. 三种资源
事件总线。 你发布事件的对象。它负责路由事件并保留事件。
订阅者。 一个资源,其中声明了你想接收哪些事件以及将它们发送到哪里。它会监视自己的事件总线,保留符合筛选条件的事件,可选择转换每个事件,然后将其发送到唯一一个目标。若要将一个事件发送到多个目标,请在同一事件总线上创建多个订阅者。
事件源。 接入事件总线的托管数据流,可以是 AWS 服务事件,也可以是合作伙伴/SaaS 来源。
名称和标识符:
- 事件总线 ARN 和订阅者 ARN 都会在名称后附加由服务生成的 ID:
arn:aws:events:us-east-1:111122223333:event-busv2/my-bus/exampleid0123456789abcdef。 请保存完整 ARN,而不是名称,因为名称本身无法唯一标识资源;删除事件总线后,以相同名称重新创建会得到不同的 ID。 - 事件源名称在账户内唯一,而非在事件总线内唯一。
- 有三个名称用于标识此服务,且彼此不同。 CLI 命令和端点主机名为
eventsv2,例如aws eventsv2 create-event-bus和eventsv2.{region}.amazonaws.com。SDK 客户端为eventbridgev2。IAM 操作和 ARN 使用与经典 EventBridge 共用的events,例如events:PutEvents和arn:aws:events:...:event-busv2/...。请参阅第 14 章。
2. 带有持久日志的路由器
事件总线会将每个事件路由给匹配的订阅者,同时还会在配置的时长内保留事件;此时长按事件总线设置,通过 StorageConfiguration.RetentionPeriodInDays 指定(1 到 365 天)。正是保留机制让其他四项功能成为可能:起始位置、暂停和恢复、重放,以及让今天创建的订阅者读取昨天发布的事件。保留窗口的起点会限制在事件总线创建时间,因此对于较新的事件总线,即使是近期的过去时间戳也可能超出窗口。
3. 从经典 EventBridge 迁移
经典规则及其目标在新事件总线上对应一个订阅者。新事件总线有四个经典版本中没有对应概念的功能:事件总线自身的保留机制、订阅者起始位置、暂停和恢复并保留待处理事件,以及采用不同负载模型的两种发布 API。最后一点会影响筛选条件的编写方式,因此原样移植的经典事件模式仅适用于 PutEvents。概念映射、可能不再适用的习惯以及分步迁移流程,请参阅
migrating-from-classic.md。
4. AWS 服务和合作伙伴事件源
事件源是一个托管式事件流,会将事件送入你的总线。你需要创建事件源,指定目标总线和一个来源,服务便会在经典 EventBridge 侧为你建立转发。无需角色,也无需投递代码:托管路径使用服务自身的身份。
Configuration 是一个带判别字段的结构,MUST 设置且只能设置一个变体:
| 变体 | 来源 | 必填成员 |
|---|---|---|
AwsServiceEventsConfiguration | 一个 AWS 服务,例如 aws.s3 | AwsService |
PartnerEventsConfiguration | 一个经典合作伙伴事件源 | PartnerEventSourceArn |
两者都可以设置可选的 Pattern,用于缩小转发范围;该模式会在经典侧根据经典信封进行评估。你的模式 MUST NOT 包含 source 键,也 MUST NOT 在顶层包含 account 或 region,因为服务会自行设置这些字段,以便将转发限定到你的账户和来源。
转发的事件会以完整的经典信封到达。Data 中保存该信封,ContentType 为 application/eventbridge+json,你的内容位于 $events.Data.detail,而来源和 detail-type 位于 SystemMetadata 中,分别为 aws:Source 和 aws:DetailType。因此,经典规则的 source 筛选条件不会直接适用:等效做法是使用 SYSTEM_METADATA 筛选条件 {"aws:Source":["aws.s3"]}。
**只有这一对 SystemMetadata 字段能证明事件由 AWS 服务或合作伙伴生成。**任何发布调用都无法写入这两个键。原始负载可以完全仿造该信封,因此,对负载中 source 字段使用 DATA 筛选条件时,伪造事件和真实事件都会匹配。在来源可信度很重要时,你 SHOULD 筛选 aws:Source,并且 MUST 匹配其值,而不只是判断它是否存在,因为直接调用 PutEvents 也会设置该键,值取自其自身的 Source,且该值永远不会带有 aws. 前缀。
EventBusArn 不可变。恢复方式取决于失败类型:如果状态为 CREATE_FAILED 或 UPDATE_FAILED,UpdateEventSource 会使经典侧恢复为与你的记录一致;如果状态为 DELETE_FAILED,唯一的恢复方式是再次执行删除操作。
总线所有者在创建时拥有控制权。CreateEventSource 会根据目标总线上的 events:source 条件键进行授权;对于已存在的事件流,所有者可使用 RevokeResource 停止它(第 22 章)。前置条件、加密、死信处理,以及经典账户中会显示的内容,请参阅 event-sources.md。
5. 选择发布 API
此选择决定载荷形状,而载荷形状又决定了你接下来要编写的每个筛选器、转换器和目标参数。
PutEvents | PutRawEvents | |
|---|---|---|
| 载荷字段 | Detail,一个 JSON 字符串 | Data,一个 base64 数据块 |
| 载荷必须为 JSON | 是 | 否,任何格式均可 |
| 每个条目的必填项 | Source、DetailType | Data、SystemMetadata |
ContentType | 不接受;服务会写入 application/eventbridge+json | 必填,位于每个条目的 SystemMetadata 中 |
| 经典样式字段 | 可使用 Resources、Time | 不存在 |
| 自定义元数据 | 否 | Metadata,最多 100 个键 |
| 排序和去重输入 | SystemMetadata.EventGroupId、SystemMetadata.DeduplicationId | 同样是这两个字段 |
对于需要经典样式封装的 JSON 事件,请使用 PutEvents。对于二进制或非 JSON 载荷、自定义元数据键,或需要载荷按原样传递的情况,请使用 PutRawEvents。
两者都会按请求条目的顺序返回对应的结果条目,因此可按索引进行关联。每个结果条目都包含 SuccessCode,或 ErrorCode 和 ErrorMessage。SuccessCode 的值为 PUBLISHED 或 DEDUPLICATED,而且 DEDUPLICATED 表示成功,不是错误。 如果代码将每次成功都视为新事件,就会误以为去重导致了投递问题。
发布 Avro 或 Protobuf 时,必须在每个发布请求中指定架构注册表,而不是在总线上指定;如果将注册表配置在错误的位置,事件就无法解码。application/octet-stream 无需注册表,因为服务根本不会解码这些字节(schema-registries.md)。
6. 寻址:每个字段的位置
筛选器、转换器和目标参数共用一种寻址模型,而且 两种发布 API 的寻址方式并不相同。 每个事件都会通过三个顶层名称进行投递:Data(载荷)、Metadata(你的自定义键,仅限 PutRawEvents)和 SystemMetadata(服务分配的字段及排序字段)。通过原始方式发布的载荷直接位于 Data 中;PutEvents 载荷则位于经典封装内,在 detail 下多嵌套一层。因此,同一字段对于一种 API 的路径是 $events.Data.m,对于另一种则是 $events.Data.detail.m;使用错误的形式不会报错:它只会解析为空,筛选器也不会匹配,转换器则不会输出任何内容。如果通过这两种 API 向同一总线发布事件,请编写同时适用于两者的表达式,或为每种流量类型设置各自的订阅者;不存在适用于两者的通用寻址形式。两个封装的完整内容及所有 SystemMetadata 字段,请参阅 filters-and-expressions.md。
7. 筛选
订阅者的 FilterConfiguration 包含一个 Filters 列表,事件必须匹配列表中的每个筛选器才能投递:筛选器之间是 AND 关系,而不是 OR 关系。每个筛选器都有一个 Pattern 和一个 Scope(DATA、METADATA 或 SYSTEM_METADATA),每个范围只能有一个筛选器。DATA 模式根据第 6 章所述的形状编写,因此一个模式无法同时适用于两种发布 API;每个模式只对其中一种 API 有效,对另一种 API 则会静默地匹配不到任何内容。创建时 FilterConfiguration 是可选的;未配置该项的订阅者会接收总线上的每个事件。无法匹配任何内容的筛选器与故障订阅者无法区分,因此请通过观察目标,确认一个应当匹配的情况和一个不应匹配的情况。
8. 转换
订阅者的 Transformer 有三种类型:RAW(默认)仅传递负载,WITH_METADATA 传递三段式封套,JSONATA 传递表达式的结果。JSONata 表达式以 {% %} 分隔符包裹,并将事件作为 $events 来访问,访问方式与第 6 章完全相同。大多数标量目标参数也接受相同格式的表达式。有些成员不接受表达式,必须使用字面值:API Gateway 标头名称、消息属性的 BinaryValue 和 InvocationType。表达式只会在创建时进行语法检查,因此其结果要到传递时才能确定。若 JSONATA 转换器的表达式抛出错误或求值结果为空,就会导致客户责任的传递失败,因此应当进行测试。
9. 目标及其参数块
InvokeConfiguration 包含 TargetArn、RoleArn,以及最多一个与目标匹配的参数块。通用目标必须携带其参数块;任何类型化参数块都可以省略。经典事件总线和 Firehose 传输流都是无需参数块的有效目标。
服务会根据 ARN 解析目标类型,并在存储任何内容之前检查其负责的约束:参数块是否与目标匹配、ARN 的区域、分区和账户是否属于该服务,以及每个表达式是否都能解析。它不会复刻目标 API 自身的参数语法、取值范围、标识符限制或该 API 要求的成员——这些仍由目标负责,因此,目标会拒绝的请求在创建时仍会被接受,并在传递时失败。
- 你必须提供通用目标所要求的参数块。 类型化参数块可以省略:
KinesisParameters: {}会被存储,Kinesis 在被调用时会报告缺少PartitionKey。 - 你不得在每条消息的字段中放入常量,因为固定的去重 ID 会导致目标丢弃第一条消息之后的所有消息。两种形式都不会针对目标的取值范围、必填要求或 FIFO 适用性进行检查,因此,值错误或缺失都会导致传递失败。
- 你应当检查目标服务自身的规则。 目标会在传递时检查其是否存在、是否可访问、是否已授权、封套后的大小,以及其 API 所需的字段。
- 你应当在目标端确认,因为
PUBLISHED响应并不代表已传递,批处理 API 返回的 HTTP 200 也不代表已传递,因为其中可能包含单独失败的条目。 - 测试前,你必须附加死信队列并启用日志,还必须向传递角色授予该队列上的
sqs:SendMessage权限,否则失败不会留下任何信号。
每条规则的失败模式、确切的拒绝消息和各目标的参数块,详见 target-configuration.md。在编写调用本身之前,请先加载 target-contract.md,查看必填字段列表、每种目标类型的一个可用示例,以及传递错误分类。
10. 通用目标
通用目标可直接调用任何受支持的 AWS API,无需中间函数。目标 ARN 具有固定格式:
arn:{partition}:events:::aws-sdk:{service}:{apiAction}
有四点需要正确设置,每一点设置错误都会在创建时失败,并显示说明问题的消息:
apiAction 使用驼峰命名法,首字母小写(putItem);service 是 SDK 服务 ID,并不总是显而易见的单词(Step Functions 的值是 sfn);UniversalTargetParameters.Input 为必填项,保存 API 请求的 JSON 或可生成该请求的 JSONata 表达式;BatchConfiguration 为必填项。服务的验证文本会将通用目标简称为“USI target”;两者含义相同。
11. 排序与去重
排序是订阅者的属性。Type 为 UNORDERED(不保证顺序)或 FIFO(在事件组内有序),发布时会按 SystemMetadata.EventGroupId 对事件分组。FIFO 目标会对组 ID 强制执行自身的长度和字符限制;无法投递的事件会阻塞其所属组中的后续事件,而同一订阅者上的其他组仍可继续处理,因此组 ID 应保持简短,不要根据无界输入生成组 ID。
去重在发布时进行,有两种方式。请求中的 DeduplicationConfiguration.DeduplicationType: CONTENT_BASED 会对事件内容进行哈希,而 CONTENT_BASED 是唯一的
DeduplicationType 值。如果要根据自己的键去重,请省略 DeduplicationConfiguration,并在每个条目的 SystemMetadata.DeduplicationId 中设置该键。无论采用哪种方式,被抑制的重复事件都会返回
SuccessCode: DEDUPLICATED。
请将这两个概念区分开。总线级去重决定是否接受事件。FIFO 目标自身的去重 ID(在目标参数块中设置)决定该目标是否接受投递。这是不同层级中的不同字段,而且第二个是每条消息各自的值(第 9 章,规则 2)。
12. 重试与死信
RetryPolicy 有三个成员:
| 成员 | 范围 | 默认值 |
|---|---|---|
MaxRetryAttempts | 0-185 | 5 |
MaxEventAgeInSeconds | 60-86400 | 300 |
RetryStrategy | ALL | ALL |
投递会在先达到的限制处停止,失败的投递会一直重试到那时。因此,只有在 MaxEventAgeInSeconds 窗口结束后,才能确定“没有收到任何内容”。
OnFailureConfiguration.Arn 指定用于死信处理的 SQS 队列,SQS 是唯一受支持的目标。事件源不接受 FIFO 队列,并且会返回唯一的消息
OnFailureConfiguration.Arn must name a standard SQS queue: FIFO queues are not supported as EventSource dead-letter queues;
订阅者则接受 FIFO 队列,因此这两种资源在这一点上有所不同。还需规划应对另外两个限制:死信记录通过 ID 和时间戳标识失败的事件,不包含负载,因此重放需要事件仍处于保留期内;并且投递角色必须能够写入死信队列,否则失败事件无处可去,会悄无声息地消失。
13. 投递权限
InvokeConfiguration.RoleArn 是服务用来调用目标的角色。该角色必须属于调用账户,其信任策略必须允许 events.amazonaws.com 服务主体,并且该策略应当通过 aws:SourceAccount 和 aws:SourceArn 设置条件。该角色必须具有目标所需的操作(sqs:SendMessage、sns:Publish、lambda:InvokeFunction、kinesis:PutRecords、states:StartExecution,或通用目标所需的其他操作),并且对死信队列具有**sqs:SendMessage 权限**,否则投递会失败,不会写入失败记录,也无法观察到任何情况。
CreateSubscriber 还会检查该角色的 iam:PassRole 权限,因此无法传递的角色会在目标验证运行前返回
AccessDeniedException。上述列表还遗漏了四项:Kinesis 投递调用 PutRecords,Firehose 调用 PutRecordBatch,API Gateway 需要 execute-api:Invoke,API destination 需要 events:InvokeApiDestination。
创建时会检查目标 ARN 的格式、类型、区域、分区和账户,但不会检查其是否存在或是否可访问:格式正确但未指向任何资源的 ARN 也会被存储,并在投递时失败。
14. 授权:调用方需要什么
第 13 章介绍 EventBridge 用于调用目标的角色。本章介绍调用方需要什么才能访问 API。
每个操作名称都以 events: 开头。 CLI 命令和端点主机名是 eventsv2,SDK 客户端的名称是 eventbridgev2,但 IAM 命名空间是 events,与经典 EventBridge 共用。你绝不能在 IAM 策略中写入 eventbridgev2: 或 eventsv2:,因为这两个名称都不是有效操作,而且都会默认拒绝:策略虽然能通过验证,但不会授予任何权限。从刚运行的命令生成策略并授予 eventsv2:PutEvents,就是这种情况的常见原因。逐项名称对照表见 authorization.md。
发布按条目针对事件总线 ARN 授权,不支持部分授权:如果任一条目未通过条件检查,整个请求都会被拒绝,因此一个批次的授权范围取决于其中授权最少的条目。
创建订阅方或事件源时,授权针对的是事件总线,因此事件总线是跨账户授权点:事件总线所有者在此决定其他账户是否可以附加任何内容。
使用你提供的角色将事件转发到事件总线时,授权在接收事件时按事件进行:真实的 AWS 或合作伙伴事件需要 events:PutEvents,你自行生成的任何事件都需要 events:PutRawEvents。因此,转发器同时处理这两类事件时,必须授予这两个操作,否则只授予其中一个会导致一半事件流被静默拒绝。条件键、创建时的逐项检查以及撤销语义见 authorization.md。
15. 预置与资源状态
创建事件总线是异步操作:CreateEventBus 返回时状态为 State: CREATING,之后事件总线才会变为可用。请使用 waiter,而不要手动编写轮询逻辑,因为遇到失败状态时 waiter 会快速失败,并显示 StateReason,而不是一直轮询到超时:
aws eventsv2 wait event-bus-active --event-bus-arn "$BUS_ARN"
事件总线有七种状态,值得注意的不对称之处在于两种失败状态:UPDATE_FAILED 可以原地恢复,而 CREATE_FAILED 不可以。 创建失败后只能删除,因此必须删除该事件总线并重新创建。删除事件总线前,请先删除订阅方和事件源;如果事件总线仍有任一对象,调用 DeleteEventBus 会返回 ResourceInUseException,并在消息中指出阻止删除的对象类型。已撤销的订阅方和事件源不会阻止删除。
创建操作通过 ClientToken 实现幂等。 CreateEventBus、CreateSubscriber 和 CreateEventSource 都接受一个令牌,重试时携带相同令牌会返回原始结果,而不是创建第二个资源。如果省略该字段,SDK 会在每次调用时生成新的令牌,因此你自己的代码发起重试时会构造新请求、获取新令牌并创建第二个资源。因此,只要重试可能跨越进程、队列或工作流步骤,你就必须提供自己的 ClientToken。 不匹配错误和名称冲突详见 provisioning-and-state.md。
16. 安全更新
每个更新 API 都遵循一条规则;如果理解有误,就会静默丢弃你无意更改的配置:
省略顶层成员表示保持不变。提供配置块则会替换整个配置块。
因此,为了更改其中一个字段而在更新请求中提供 Configuration、FilterConfiguration 或 LogConfiguration,会清除该配置块中的所有其他字段。 更新事件源时如果省略 Pattern,返回的事件源就完全没有模式,过滤器会扩大到匹配所有内容,而且不会发出警告。因此,你必须读取资源,修改整个配置块,将整个配置块写回,然后再次读取资源,因为再次读取是确认已存储内容的唯一方式。
17. 暂停、恢复和重放
没有单独的重放 API。重放是订阅者的起始位置,会根据总线保留的事件进行评估,因此仍在保留期内的内容都可以重新读取。
- 创建时的
StartingPosition可以是LATEST(仅接收订阅者创建后发布的事件),也可以是POINT_IN_TIME(从保留历史中的某个时间点开始)。 - 暂停是通过
UpdateSubscriber将State设为STOPPED。积压事件会不断累积,但受保留期限制;恢复时是传递还是跳过积压事件,由ResumePosition决定。 - 重放的事件会带有标记。
SystemMetadata."aws:DeliveryType"的值为REPLAY,而不是LIVE,因此使用方可以确保重放具有幂等性。 - 重放启动时会有延迟,之后会以实时速度运行,因此在判定重放是否失效之前,请考虑这段延迟。
18. 可观测性:指标和日志
两个方面可以告诉你服务正在做什么,但它们的默认设置恰好相反。
发布指标默认启用,位于 AWS/EventsV2 命名空间中,维度为 {EventBus},以及用于归因到事件源的流量的 {EventBus, EventSource} 和用于入口字节数的 {EventBus, PublisherAccount}。将 PublishEventsApproximateCallCount 与 PublishEventsApproximateSuccessCallCount 对比,是确认生产者是否已向总线发送请求的最简单方法。结果指标统计的是调用次数,而不是事件数,因此只要调用返回了响应,即使其中的所有条目都被拒绝,也会计为成功;要判断事件是否成功送达,应查看 PublishEventsEntryCount 和 PublishEventsFailedEntriesCount。EventBus 维度的值不是总线 ARN;使用 ARN 查询不会返回数据,看起来就像没有流量一样。
订阅者日志默认关闭,要让日志生效,需要满足两个条件:将 LogConfiguration.Level 调高至 OFF 以上,并配置 CloudWatch Logs 交付日志,将订阅者连接到日志组。请在调试交付问题之前完成这两项设置,而不是之后。交付设置、指标列表和 EVENT_DELIVERY_ATTEMPT 记录字段见 observability.md。
19. 验证交付
发布响应表示服务已接受事件,但并不能说明事件是否已交付。要确认事件是否到达,请查看目标端。
健康的交付会很快到达目标,因此尚未及时到达的事件很可能是交付失败,而不是仍在传输中。 但只有在重试窗口结束后,才能据此断定“没有事件到达”,因为在此之前,交付失败的事件仍会继续重试。
两种计数错误会让正常工作的配置看起来像是出了问题。从 SQS 队列读取消息却不删除,会导致消息被重复读取,因此原始计数会高估交付次数。此外,共享目标会累积先前运行产生的消息,因此每次实验都应使用全新的目标,或使用本次运行独有的标记。
20. 已发布但始终未到达
几乎所有交付问题的表现都一样:发布成功,但目标为空。你 SHOULD 按顺序执行 delivery-troubleshooting.md 中的步骤;其中列出了 11 种原因,并按最常见的原因优先排序。
无需打开文件即可尝试的三个快捷方法:
- 你 SHOULD 首先检查
PublishEventsEntryCount(第 18 章)。如果值为 0,问题就出在总线上游,此时下游的任何情况都无关紧要。 - 你 SHOULD 开启订阅者日志。 设置
INFO和IncludePayload: FULL,即可查看每次尝试的错误和发送的确切target_input,无需等待重试耗尽。 - 若要查看服务所看到的事件内容,你 MAY 添加第二个订阅者,设置
Transformer: { Type: WITH_METADATA }且不设置筛选条件,并将其指向你拥有的队列。
21. 错误和客户端重试
批次响应按条目返回。 发布请求可能在请求级别成功,但部分条目失败,因此请检查 FailedEntryCount 和每个条目,而不只是 HTTP 状态码。
某些格式错误的输入会导致整个请求失败,而非仅一个条目失败。 反序列化请求时捕获到的任何错误都会拒绝整个批次,并连带拒绝其中有效的条目。请在客户端按条目验证,并将批次保持在足够小的规模,以便丢失一个批次时损失不大。
可重试的错误。 ConcurrentModificationException 和 ThrottlingException 可通过退避重试。InvalidInputException、AccessDeniedException、ResourceNotFoundException 和 IdempotentParameterMismatchException 不可重试;请修正请求。
持续出现 500 错误时,首先应检查客户端的线缆类型问题。 常见原因是发送了错误 JSON 类型的值,例如预期为字符串却传入数字,或预期为纪元秒数却传入 ISO-8601 字符串。根据约定,SDK 会重试 500 错误,但重试无法修复格式错误的请求,因此升级处理前请先检查类型。
22. 安全、加密、共享和标记
- 加密通过总线上的
EncryptionConfiguration.KmsKeyIdentifier配置。调用方在创建时需要对密钥拥有kms:DescribeKey权限;对于 CMK 总线,每个发布者也都需要对该密钥拥有kms:Decrypt权限,因为无法读取总线事件的调用方不允许写入事件。如果服务端的密钥策略不可用,总线会进入CREATE_FAILED状态,并显示StateReason: KMS_ACCESS_DENIED(参见 security-and-sharing.md)。 - 要与其他账户共享总线,请使用 AWS RAM。 资源策略可用于处理 RAM 无法表达的权限,但手写策略在 RAM 中不可见,因此需要由你负责跟踪。
- 某些操作仅限总线所有者执行,包括撤销共享资源,因此仅授予权限并不总是足够。撤销是终止性的,且仅适用于指定的单个资源;因此,如果要停止某个账户,而不是某个资源,还需在总线资源策略中拒绝该账户的
events:CreateSubscriber和events:CreateEventSource权限(参见 authorization.md)。
23. 成本、配额和平台集成
有四项因素会影响设计决策。当前价格和配额值请参阅 EventBridge 定价页面和 Service Quotas,而非本文档。
- 接收和传送都会按 KB 向上取整计费,因此,许多小事件的费用会高于按字节总量估算的费用;将相关事实批量放入一个事件更省钱。
- “增强操作”会单独计费:JSONata 求值、架构反序列化和
CONTENT_BASED去重。如果已有幂等键,优先使用每个条目的DeduplicationId,且不设置DeduplicationConfiguration。 - 两个发布 API 的节流额度按账户合并计算,因此在两者间分流流量的服务共用一个额度。订阅方管理有独立的账户级限额,因此发布尚有余量时,
CreateSubscriber和DeleteSubscriber仍可能受到节流。遇到ThrottlingException时请使用退避策略(第 21 章)。 - CloudFormation 通过
AWS::EventsV2::支持新总线,包含三种类型。六个订阅方属性仅可在创建时设置,替换时会先删除再创建,因此更改模板中的目标 ARN 可能会导致间隙期间发布的事件悄然丢失。