使用 Amazon SNS 构建 Pub/Sub 消息传递 - 扇出模式与过滤

讲解 SNS 基于主题的消息传递、订阅过滤器以及 SQS 扇出模式。

SNS 概述

SNS 是一种 Pub/Sub 消息传递服务,每个主题最多支持 1,250 万个订阅,消息大小上限为 256 KB。发布者向主题发送消息,消息会被分发给所有订阅该主题的订阅者。与 SQS 的点对点队列不同,SNS 实现一对多的扇出。Standard 主题以近乎无限的吞吐量进行尽力排序投递,FIFO 主题以每秒 300 条消息(批处理时为 3,000 条)提供严格的顺序保证和去重。订阅协议支持 SQS、Lambda、HTTP/S、Email、SMS、Kinesis Data Firehose,可从一个主题同时向使用不同协议的多个订阅者投递。

扇出与过滤

SNS + SQS 扇出模式中,多个 SQS 队列订阅同一个 SNS 主题,将一条消息并行分发给多个消费者。典型场景是将订单事件同时分发到库存管理队列、配送队列和通知队列。订阅过滤策略基于消息属性进行过滤,使订阅者仅接收所需消息。过滤策略可将范围设置为 MessageAttributes(默认)或 MessageBody,支持字符串精确匹配、前缀匹配、数值范围、exists 运算符的复合条件。FIFO 主题通过消息组 ID 控制顺序,同一组内的消息严格按 FIFO 投递。不同组之间独立并行投递,可在确保吞吐量的同时仅对需要的部分保证顺序。

死信队列与重试

为 SNS 订阅配置死信队列 (DLQ) 后,投递失败的消息会被转移到 SQS 队列中。HTTP/S 端点的投递通过重试策略控制重试次数和间隔。HTTP/S 投递重试分为 3 个阶段:即时重试(1 次)、退避阶段(10 次,指数退避)、退避后阶段(38 次,20 秒间隔),共计 49 次重试。Lambda 订阅遵循 Lambda 异步调用的重试策略。投递状态日志输出到 CloudWatch Logs,可分析投递成功率和错误原因。投递状态日志支持分别设置成功和失败的采样率,通常将成功日志采样率控制在 10% 左右以管理成本。跨账户的主题访问通过基于资源的策略进行控制。 如果您想系统学习 SNS,相关书籍 (Amazon)也可作为参考。

设计最佳实践与陷阱

消息属性设计直接影响过滤效率。建议将过滤使用的属性包含在 MessageAttributes 中,使订阅者端无需解析负载本体。Standard 主题可能重复投递消息(至少一次),因此消费者需确保幂等性。处理大型消息负载(超过 256 KB)时,采用 Extended Client Library 模式:将负载存储在 S3 中,SNS 消息仅包含 S3 引用。FIFO 主题中 MessageDeduplicationId 的设计至关重要,启用基于内容的去重后会使用本体哈希自动判定,但需注意意外的去重。加密有 SSE-SNS(AWS 托管密钥)和 SSE-KMS(CMK)两种方式,跨账户场景需在 CMK 密钥策略中授予目标账户解密权限。

与 EventBridge 的选择

SNS 和 EventBridge 都是事件驱动架构的基础,但适用领域不同。SNS 适用于高吞吐量(Standard 主题近乎无限)且简单属性过滤即可满足需求的场景。EventBridge 适用于需要对事件结构(JSON 正文的任意字段)进行高级模式匹配、定时触发器或 SaaS 集成(Shopify、Zendesk 等)的场景。在费用方面,SNS 向 SQS 投递免费而 EventBridge 按事件计费,因此将同一事件扇出到多个目标的纯 Pub/Sub 工作负载中 SNS 成本更低。另一方面,少数规则执行复杂路由的场景中 EventBridge 的规则设计维护性更优。两者组合——EventBridge 路由后 SNS 扇出的架构也是有效的方案。

SNS 的成本管理

SNS 的成本由发布次数和投递目标协议决定。向 SQS 投递免费,因此 SNS → SQS → Lambda 模式在某些情况下比 SNS → Lambda 直接投递更具成本优势。HTTP/S 投递每 10 万次 0.06 美元,SMS 因目标国而异(美国 0.00645 美元/条,日本 0.07086 美元/条)。通过消息过滤减少不必要的投递,优化 Lambda 执行次数。处理大量消息时,可通过消息批量化(在一条消息中包含多个事件)减少发布次数。FIFO 主题费用是 Standard 的 2 倍(每百万请求 0.50 美元),因此在不需要顺序保证的部分使用 Standard 来控制成本。

总结

SNS 是通过 Pub/Sub 消息传递实现扇出模式的服务。订阅过滤器基于属性进行高效消息路由,DLQ 确保捕获投递失败的消息。由于向 SQS 投递免费,SNS → SQS → Lambda 模式可构建高性价比的异步处理架构,FIFO 主题仅在需要的部分应用顺序保证。根据吞吐量需求和路由复杂度合理选择 SNS 和 EventBridge,可设计最优的事件驱动架构。