使用 Amazon SQS 消息 - Amazon Simple Queue Service
Amazon Web Services 文档中描述的 Amazon Web Services 服务或功能可能因区域而异。要查看适用于中国区域的差异,请参阅 中国的 Amazon Web Services 服务入门 (PDF)

本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。

使用 Amazon SQS 消息

下列准则可帮助您使用 Amazon SQS 高效地处理消息。

及时处理消息

可见性超时设置取决于您的应用程序需要多长时间来处理和删除消息。例如,如果您的应用程序处理一条消息需要花费 10 秒,并且您将可见性超时设置为 15 分钟,则在上一次处理尝试失败的情况下,您必须等待一个相对较长的时间才能再次尝试处理消息。或者,如果您的应用程序处理一条消息需要花费 10 秒,但您将可见性超时仅设置为 2 秒,则当原始使用者仍在处理消息时,另一个使用者会收到重复消息。

要确保有足够的时间处理消息,请使用下列策略之一:

  • 如果您知道(或者可以合理地估计)处理消息所需的时间,则将消息的可见性超时 延长至处理消息所需的最长时间并删除消息。有关更多信息,请参阅配置可见性超时

  • 如果您不知道处理消息需要多长时间,请为您的使用者流程创建检测信号:指定初始可见性超时(例如 2 分钟),然后(只要您的使用者仍在处理该消息),就可以每分钟将可见性超时延长 2 分钟。

    重要

    最大可见性超时为从 Amazon SQS 收到 ReceiveMessage 请求时起 12 小时。延长可见性超时不会重置 12 小时的最大值。

    此外,您可能无法将单个消息的超时时间设置为 ReceiveMessage 请求启动计时器后的整整 12 小时(即 43200 秒)。例如,如果您收到一条消息,并立即通过发送 ChangeMessageVisibility 调用,将 VisibilityTimeout 设置为 43200 秒,以设置 12 小时的最大值,则该消息很可能会失败。但是,除非通过 ReceiveMessage 请求消息和更新可见性超时之间存在明显的延迟,否则使用 43195 秒这个值会起到作用。如果您的使用者需要超过 12 小时,请考虑使用 Step Functions。

处理请求错误

要处理请求错误,请使用下列策略之一:

  • 如果您使用 Amazon SDK,则已经可以任意使用自动重试和回退逻辑。有关更多信息,请参阅《Amazon Web Services 一般参考》中的 Amazon 中的错误重试和指数回退

  • 如果您未使用 Amazon SDK 特征进行重试和回退,则在未收到任何消息、超时或来自 Amazon SQS 的错误消息的情况下重试 ReceiveMessage 操作之前,应允许暂停(例如,200 毫秒)。对于将产生相同结果的 ReceiveMessage 的后续使用,应允许更长的暂停时间(例如 400 毫秒)。

设置长轮询

ReceiveMessage API 操作的等待时间大于 0 时,长轮询生效。最长长轮询等待时间为 20 秒。长轮询通过消除空响应的数量(ReceiveMessage 请求时没有消息可用时)并消除假的空响应(消息可用但未包含在响应中),帮助降低使用 Amazon SQS 的成本。有关更多信息,请参阅Amazon SQS 短轮询和长轮询

要确保最佳消息处理,请使用以下策略:

  • 在大多数情况下,您可以将 ReceiveMessage 等待时间设置为 20 秒。如果 20 秒对您的应用程序来说太长,则可设置较短的 ReceiveMessage 等待时间(最少 1 秒)。如果不使用 Amazon SDK 访问 Amazon SQS,或者将 Amazon SDK 配置为具有较短的等待时间,则可能必须修改 Amazon SQS 客户端,才能允许时间更长的请求或对长轮询使用较短的等待时间。

  • 如果您对多个队列实施长轮询,则对每个队列使用一个线程,而不是对所有队列使用单个线程。如果对每个队列使用一个线程,您的应用程序将能够在各队列中的消息可用时处理这些消息;如果使用单个线程来轮询多个队列,则可能导致应用程序在等待(最长 20 秒)没有任何可用消息的队列时无法处理其他队列中的可用消息。

重要

为避免 HTTP 错误,请确保 ReceiveMessage 请求的 HTTP 响应超时比 WaitTimeSeconds 参数更长。有关更多信息,请参阅 ReceiveMessage

捕获有问题的消息

要捕获所有无法处理的消息,并要收集准确的 CloudWatch 指标,请配置死信队列

  • 在源队列无法将消息处理指定次数后,重新驱动策略会将消息重定向到死信队列。

  • 使用死信队列将减少消息数并减小向您公开毒丸消息(可接收但无法处理的消息)的几率。

  • 在队列中包含毒丸消息可能导致 ApproximateAgeOfOldestMessage CloudWatch 指标失真,因为它会提供不正确的毒丸消息存在时间。配置死信队列有助于避免在使用此指标时发出错误警报。

设置死信队列保留期

对于标准队列,消息的到期时间始终基于其原始入队时间戳。将消息移至死信队列时,入队时间戳保持不变。ApproximateAgeOfOldestMessage 指标指示消息何时移入死信队列,而不是消息最初发送的时间。例如,假设一条消息在原始队列中停留了 1 天,然后才移至死信队列。如果死信队列的保留期为 4 天,则消息将在 3 天后从死信队列中删除,且 ApproximateAgeOfOldestMessage 为 3 天。因此,最佳实践是始终将死信队列的保留期设置为比原始队列的保留期长。

对于 FIFO 队列,当消息移到死信队列时,入队时间戳会重置。ApproximateAgeOfOldestMessage 指标指示消息何时移动到死信队列。在上面的同一个示例中,消息在 4 天后从死信队列中删除,且 ApproximateAgeOfOldestMessage 为 4 天。

避免不一致的消息处理

由于 Amazon SQS 是一个分布式系统,因此,即使在从 ReceiveMessage API 方法调用成功返回时 Amazon SQS 将消息标记为已发送,使用者也可能不会收到消息。在这种情况下,Amazon SQS 将消息记录为至少已发送一次,即使使用者从未收到过也是如此。由于在这些情况下不会再尝试发送消息,因此我们不建议将死信队列的最大接收数量设置为 1。

实施请求-响应系统

实施请求-响应和远程程序调用 (RPC) 系统时,请记住以下最佳实践:

  • 请勿为每个消息 创建回复队列。而是在启动时为每个创建者创建回复队列,使用关联 ID 消息属性将回复映射到请求。

  • 不要让创建者共享回复队列。这可能会导致创建者收到针对另一个创建者的响应消息。

有关使用临时队列客户端实施请求-响应模式的更多信息,请参阅 请求-响应消息收发模式(虚拟队列)