亚马逊AWS官方博客
Amazon SNS FIFO(先进先出)发布/订阅消息传递简介
在设计分布式软件体系结构时,定义服务交换信息的方式非常重要。例如,使用异步通信解耦组件和简化缩放,从而减少更改带来的影响,并使新功能发布变得更加容易。
异步服务到服务通信的两种最常见形式是消息队列和发布/订阅消息传递:
- 使用消息队列时,消息将存储在队列中,直到消息被使用者处理和删除。在 AWS 上,Amazon Simple Queue Service (SQS) 提供完全托管的消息队列服务,无需管理开销。
- 通过发布/订阅消息传递,发布到某个主题的消息将传递给该主题的所有订阅者。在 AWS 上,Amazon Simple Notification Service (SNS) 是一种完全托管的发布/订阅消息传递服务,可向大量订阅者传递消息。每个订阅者还可以设置筛选策略,只接收其感兴趣的消息。
当您想要将消息扇出到多个应用程序时,可以使用主题,当想要向一个应用程序发送消息时,可以使用队列。将主题和队列结合使用,可以将微服务、分布式系统和无服务器应用程序解耦。
借助 SQS,您可以使用 FIFO(先进先出)队列来保留消息发送和接收的顺序,并避免多次处理一条消息。
SNS FIFO 主题简介
现在,我们通过引入 SNS FIFO 主题,增加类似的发布/订阅消息传递功能,为一个或多个订阅者提供严格的消息排序和去除重复的消息传递。
FIFO 主题管理排序和重复数据删除的方式与 FIFO 队列类似:
排序 – 在向 FIFO 主题发布消息时,可以通过包括消息组 ID 来配置消息组。对于每个消息组 ID,所有消息都按照到达顺序进行发送和传递。例如,要确保按顺序传递与同一客户相关的消息,您可以使用客户的账号作为消息组 ID 将这些消息发布到主题。FIFO 主题和队列的消息组数量没有限制。您不需要事先声明消息组 ID,任何值都可以正常工作。如果在消息之间没有逻辑区分,则可以简单地为所有消息使用相同的消息组 ID,这样将产生单独的一组有顺序的消息。消息组 ID 将传递给任何已订阅的 FIFO 队列。
重复数据删除 – 分布式系统(如 SNS)和客户端应用程序有时会生成重复的消息。您可以通过两种方式避免来自主题的重复消息传递:在主题上启用基于内容的重复数据删除,或者向您发布的消息添加重复数据删除 ID。借助基于内容的重复数据删除功能,SNS 可对消息正文使用 SHA-256 哈希来生成消息重复数据删除 ID。成功发布具有特定重复数据删除 ID 的消息后,在 5 分钟的时间内,具有相同重复数据删除 ID 的所有消息都将被接受但不会传递。如果为 FIFO 队列订阅 FIFO 主题,则重复数据删除 ID 将传递给队列,并且 SQS 将使用它来避免接收重复消息。
您可以将 FIFO 主题和队列结合使用,以简化操作顺序和事件至关重要或者无法容忍重复的应用程序实施。例如,处理财务操作和库存更新,或异步应用从客户端设备收到的命令。 FIFO 队列可以使用 FIFO 主题中的消息筛选功能来有选择地接收消息的子集,而不是发布到主题的每条消息。
如何使用 SNS FIFO 主题
FIFO 主题经常用于在收到需要按顺序处理的更新时提供帮助。例如,我可以使用 FIFO 主题从客户编辑其账户配置文件的应用程序接收更新。然后,我订阅 SQS FIFO 队列到 FIFO 主题,并使用该队列作为 Lambda 函数的触发器,该函数将账户更新应用到客户管理系统使用的 Amazon DynamoDB 表,该表需要保持同步。
FIFO 主题带来的解耦能力使添加新功能变得更加容易,并且对现有应用程序的影响最小。例如,为了给我的忠实客户提供额外促销作为奖励,我添加了一个新的 Loyalty 应用程序,该应用程序将信息存储在由 Amazon Aurora 管理的关系数据库中。为了保持 Loyalty 数据库中存储的客户信息与我的其他应用程序同步,我可以为相同的 FIFO 主题订阅一个新的 FIFO 队列,并添加新的 Lambda 函数,该函数按照生成顺序接收客户更新,并将更新应用至 Loyalty 数据库。通过这种方式,我不需要更改其他应用程序的代码和配置就能集成新的 Loyalty 应用程序。
首先,我在 SQS 控制台创建两个 FIFO 队列,将所有选项保留为默认值:
customer.fifo
队列用于处理客户管理系统中的更新。loyalty.fifo
队列帮助我收集和存储用于 Loyalty 应用程序的客户更新。
在 SNS 控制台中,我创建 updates.fifo
主题。选择 FIFO 作为类型,并启用基于内容的消息重复数据删除。
然后,订阅 customer.fifo
和 loyalty.fifo
队列到该主题。
为了能够接收消息,我在两个队列的访问策略中添加一个语句,授予 updates.fifo
主题向队列发送消息的权限。例如,对于 customer.fifo
队列,该语句为:
{
"Effect": "Allow",
"Principal": {
"Service": "sns.amazonaws.com"
},
"Action": "SQS:SendMessage",
"Resource": "arn:aws:sqs:us-east-2:123412341234:customer.fifo",
"Condition": {
"ArnLike": {
"aws:SourceArn": "arn:aws:sns:us-east-2:123412341234:updates.fifo"
}
}
}
现在,我使用 SNS 控制台按顺序发布 4 条消息,并为所有消息使用相同的消息组 ID。这样,它们将位于同一个消息组中。唯一不同的部分是消息正文,其中按顺序使用了以下内容:
Update One
Update Two
Update Three
Update One
在 SQS 控制台中,我只看到 3 条消息被传递到 FIFO 队列:
这是为什么? 在创建 FIFO 主题时,我启用了基于内容的重复数据删除功能。在 5 分钟的重复数据删除时段内,一共发送了 4 条消息。最后一条消息被识别为第一条消息的副本,但尚未传递到已订阅的队列。
我们来看一看队列中的实际消息。我使用 AWS 命令行界面 (CLI) 接收来自 SQS 的消息,使用 jq 命令行 JSON 处理器来格式化输出,并在正文中仅获取消息。
以下是 customer.fifo
队列中的消息:
以下是 loyalty.fifo
队列中的消息:
如我所料,3 条具有唯一内容的消息已按发送顺序传递到两个队列。
现已推出
您可以在所有商业区域使用 SNS FIFO 主题。 每个 FIFO 主题或 FIFO 队列每秒最多可以处理 300 个事务 (TPS)。 通过 SNS,您只需按实际使用量付费,您可以在定价页面找到更多信息。
要了解更多信息,请参阅文档。
– Danilo