该博文主要为 Amazon SQS 官方文档的机器翻译版本,另外在此基础上做了些许补充、修改。
一、Amazon SQS 基本架构
1.1.分布式队列
分布式消息传送系统有三个主要组成部分:分布式系统的组件、队列(分布在 Amazon SQS 服务器上)以及队列中的消息。
在下面的情况下,您的系统具有多个创建器(向队列发送消息的组件)以及使用者(从队列接收消息的组件)。队列(保存从 A 到 E 的消息)在多个 Amazon SQS 服务器上冗余存储消息。
1.2.消息生命周期
以下场景介绍 Amazon SQS 消息在队列中从创建到删除的整个生命周期。
(1) 创建者 (Component 1) 将 Message A 发送到一个队列,该消息在 Amazon SQS 服务器间冗余分布。
(2)使用者 (Component 2) 准备好处理消息时,就从队列使用消息,然后返回 Message A。在处理 Message A 期间,它仍保留在队列中,并且在可见性超时期间不返回至后续接收请求。
(3)使用者 (Component 2) 从队列中删除 Message A,以阻止该消息在可见性超时过期后被再次接收和处理。
注意:
Amazon SQS 会自动删除在队列中已过了最大消息保存期的消息。默认的消息保存期为 4 天。不过,您可使用 SetQueueAttributes 操作将消息保存期设为介于 60 秒和 1209600 秒 (14 天) 之间的值。
二、队列类型
Amazon SQS消息队列分为 标准队列 和 FIFO队列。下表概括了标准队列和 FIFO 队列的功能及区别,后面有更详细的队列说明。
标准队列 | FIFO队列 |
---|---|
无限吞吐量— 标准队列的每个 API 操作每秒支持接近无限的 API 调用 (SendMessage、ReceiveMessage,或者DeleteMessage)。 至少一次传递— 至少传送一次消息,但偶尔会传送消息的多个副本。 尽可能有序— 偶尔会按不同于其发送时的顺序传递。 | 高吞吐量— 如果您使用的是批处理,FIFO 队列的每个 API 方法每秒最多支持 3000 条消息 (SendMessageBatch、ReceiveMessage,或者DeleteMessageBatch)。每秒 3000 条消息代表 300 条 API 调用,每条调用包含 10 条消息的批处理。要申请提高配额,请提交支持请求。在不使用批处理的情况下,FIFO 队列的每个 API 方法(SendMessage、ReceiveMessage 或 DeleteMessage)每秒最多支持 300 个 API 调用。 确切一次处理— 消息传递一次并在使用者处理并删除它之前保持可用。不会将重复项引入到队列中。 先进先出交付— 严格保持消息的发送和接收顺序。 |
当吞吐量很重要时,请在应用程序之间发送数据,例如:
| 当事件的顺序重要时,请在应用程序之间发送数据,例如:
|
2.1.标准队列
Amazon SQS 消息队列默认为标准队列,标准队列的每个 API 操作(SendMessage、ReceiveMessage 或 DeleteMessage)每秒支持接近无限的 API 调用(详见与消息相关的配额-消息吞吐量)。标准队列支持至少一次消息传递。但是,由于存在允许近乎无限吞吐量的高度分布式架构,偶尔会有一条消息的多个副本不按顺序传送。标准队列会尽最大努力进行排序,保证了消息大致按其发送的顺序进行传送。
(1)消息传递
标准队列会尽量保持消息顺序,但可能有一条消息的多个副本可能不按顺序传送。如果您的系统需要保留订单,我们建议您使用FIFO(先进先出)队列,或者在每条消息中添加排序信息,以便在收到消息后对其重新排序。
(2)至少一次传递
Amazon SQS 会在多台服务器上存储消息的副本,以实现冗余和高可用性。在极少数情况下,当您接收或删除消息时,存储消息副本的某台服务器可能不可用。
如果出现这种情况,则该不可用服务器上的消息副本将不会被删除,并且您在接收消息时可能会再次获得该消息副本。将应用程序设计为幂等应用程序 (多次处理同一消息时,它们不应受到不利影响)。
2.2.FIFO队列
FIFO(first in first out)队列即为先进先出队列。FIFO 队列改进并补充了标准队列。此队列类型最重要的特性是先进先出配送和确切一次处理:
- 发送和接收消息的顺序严格保持一致;一条消息传送一次后就保持可用,直到使用者处理并删除它为止。
- 不会将重复项引入到队列中。
此外,FIFO 队列支持消息组,该组允许一个队列中存在多个有序的消息组。FIFO 队列中的消息组数量没有限额。
FIFO队列的每个 API 操作(SendMessage、ReceiveMessage 或 DeleteMessage)无法支持每秒接近无限的 API 调用。详见与消息相关的配额-消息吞吐量
(1)FIFO 传送逻辑
发送消息
如果多条消息连续发送到 FIFO 队列(每条消息具有不同的消息重复数据删除 ID),Amazon SQS 将存储消息并确认传输。然后,可按传输每条消息的确切顺序接收和处理消息。
在 FIFO 队列中,消息基于消息组 ID 进行排序。如果多台主机(或同一主机上的不同线程)将具有相同消息组 ID 的消息发送到 FIFO 队列,Amazon SQS 将按消息到达以供处理的顺序存储消息。要确保 Amazon SQS 保留发送和接收消息的顺序,每位创建者应使用唯一的消息组 ID 来发送其所有消息。
FIFO 队列逻辑仅应用于每个消息组 ID。每个消息组 ID 代表 Amazon SQS 队列中不同的有序的消息组。对于每一个消息组 ID,所有消息的发送和接收均严格遵循一定的顺序。但是,具有不同的消息组 ID 值的消息可能不会按顺序发送和接收。您必须将消息组 ID 与消息关联。如果您未提供消息组 ID,此操作将失败。如果需要一组有序的消息,请为要将消息发送到 FIFO 队列提供相同的消息组 ID。
接收消息
您无法请求接收具有特定消息组 ID 的消息。
当接收来自具有多个消息组 ID 的 FIFO 队列的消息时,Amazon SQS 会首先尝试尽可能多地返回具有相同消息组 ID 的消息。这时其他使用者能处理具有不同消息组 ID 的消息。
注意:
可使用 MaxNumberOfMessages 操作的 ReceiveMessage 请求参数在单次调用中接收多达 10 条消息。这些消息将保留其 FIFO 顺序且可具有相同的消息组 ID。因此,如果具有相同消息组 ID 的消息少于 10 条,则您可接收来自属于 10 条消息的同一批中其他消息组 ID 的消息,但仍按 FIFO 顺序。
多次重试
FIFO 队列允许生产者或使用者尝试多次重试:
- 如果生产者检测到失败SendMessage操作时,它可以使用相同的消息重复数据消除 ID,根据需要重试发送多次。假设创建者在重复数据消除间隔过期之前至少收到一个确认,多次重试既不会影响邮件的排序,也不会引入重复项。
- 如果使用者检测到失败ReceiveMessage操作,它可以根据需要重试次数,使用相同的接收请求尝试 ID。假设使用者在可见性超时到期之前至少收到一个确认,多次重试不会影响消息的排序。
- 当您收到具有消息组 ID 的邮件时,除非您删除该邮件或其变为可见,否则不会返回同一消息组 ID 的其他消息。
(2)确切一次处理
与标准队列不同,FIFO 队列不会引入重复消息。FIFO 队列可帮助您避免向队列发送重复消息。如果您重试SendMessage操作时,Amazon SQS 不会将任何重复消息引入队列。
要配置重复数据删除,必须执行以下操作之一:
- 启用基于内容的重复数据删除。这将指示 Amazon SQS 使用 SHA-256 哈希通过消息的正文(而不是消息的属性)生成消息重复数据删除 ID。
- 为消息显式提供消息重复数据删除 ID (或查看序列号)。
附1:与消息相关的配额
配额 | 描述 |
---|---|
批处理消息 ID | 批处理消息 ID 可以包含最多 80 个字符。可以使用以下字符:字母数字符、连字符 (-)和下划线(_)。 |
消息属性 | 一条消息可以包含最多 10 个元数据属性。 |
消息批请求 | 一个消息批请求中最多可包含 10 条消息。 |
消息内容 | 消息可以仅包含 XML、JSON 和非格式化的文本。允许以下 Unicode 字符:#x9 、 #xA 、 #xD 、 #x20 至 #xD7FF 、 #xE000 至 #xFFFD 、 #x10000 至 #x10FFFF。此列表中未包含的任何字符将被拒绝。 |
消息组 ID | 处理积压的消息,以避免积压大量具有相同消息组 ID 的消息。 |
消息保留 | 默认情况下,消息将保留 4 天。最小值为 60 秒 (1 分钟)。最大值为 1209600 秒 (14 天)。 |
消息吞吐量 |
标准队列的每个 API 操作(SendMessage、ReceiveMessage 或 DeleteMessage)每秒支持接近无限的 API 调用。
FIFO 队列:
|
消息定时器 | 消息的默认(最小)延迟为 0 秒。最长为 15 分钟。 |
消息大小 | 最小消息大小为 1 字节 (1 个字符)。最大消息大小为 262144 字节 (256 KB)。 |
消息可见性超时 | 消息的默认可见性超时为 30 秒。最短值为 0 秒。最长时间为 12 小时。 |
策略信息 | 最大配额为 8192 个字节、20 个语句、50 个委托人或 10 个条件。 |