设置可见性超时取决于你的应用程序需要多长时间来处理和删除一条消息。例如,如果你的应用程序需要10秒来处理一条消息,而你将可见性超时设置为15分钟,那么如果前一次处理尝试失败,你必须等待相对较长的时间来尝试再次处理该消息。或者,如果你的应用程序需要10秒来处理一条消息,但你只把可见性超时设置为2秒,那么当原来的消费者还在处理该消息时,另一个消费者就会收到一条重复的消息。
为了确保有足够的时间来处理信息,请使用以下策略之一:
如果你知道(或可以合理地估计)处理一条消息所需的时间,把消息的可见性超时延长到处理和删除该消息所需的最大时间。更多信息,请参阅配置可见性超时。
如果你不知道处理一条消息需要多长时间,为你的消费者进程创建一个心跳。指定初始可见性超时(例如,2分钟),然后—只要你的消费者仍然在处理消息—保持每分钟延长2分钟的可见性超时。
为了处理请求错误,请使用以下策略之一:
如果你使用AWS SDK,你已经有了自动重试和回退的逻辑,供你使用。更多信息,请参见Amazon Web Services General Reference中的Error Retries and Exponential Backoff in AWS。
如果您不使用AWS SDK的重试和后退功能,那么在没有收到任何消息、超时或来自Amazon SQS的错误消息后,在重试ReceiveMessage动作之前,请允许暂停(例如,200毫秒)。对于后续使用ReceiveMessage,并得到相同的结果,允许更长的暂停时间(例如,400毫秒)。
ReceiveMessage API动作的等待时间大于0时,长轮询就生效了。长时间轮询的最大等待时间是20秒。长轮询通过消除空响应(当ReceiveMessage请求没有可用的消息时)和假空响应(当消息可用但不包括在响应中时)的数量,帮助降低使用Amazon SQS的成本。更多信息,请参见Amazon SQS的短轮询和长轮询。
为了获得最佳的消息处理,请使用以下策略。
在大多数情况下,你可以将ReceiveMessage的等待时间设置为20秒。如果20秒对你的应用程序来说太长,可以设置一个较短的ReceiveMessage等待时间(最少1秒)。如果你不使用AWS SDK来访问Amazon SQS,或者你将AWS SDK配置为较短的等待时间,你可能必须修改你的Amazon SQS客户端,以允许较长的请求或对长轮询使用较短的等待时间。
如果您为多个队列实施长轮询,请为每个队列使用一个线程,而不是为所有队列使用一个线程。为每个队列使用一个线程可以让你的应用程序在每个队列中的消息可用时进行处理,而为多个队列轮询使用一个线程可能会导致你的应用程序无法处理其他队列中可用的消息,同时应用程序在等待(长达20秒)没有任何可用消息的队列。
要捕获所有无法处理的消息,并收集准确的 CloudWatch 指标,请配置一个死信队列。
在源队列未能处理消息达到指定次数后,redrive策略会将消息重定向到死信队列。
使用死信队列减少了消息的数量,并减少了暴露在毒丸消息(收到但无法处理的消息)中的可能性。
在队列中包括毒丸消息会扭曲 ApproximateAgeOfOldestMessage CloudWatch 衡量标准,因为它给出了毒丸消息的错误年龄。配置一个死信队列有助于在使用这个指标时避免错误的警报。
一条消息的过期总是基于它最初的enqueue时间戳。当一个消息被转移到死信队列时,enqueue的时间戳是不变的。ApproximateAgeOfOldestMessage指标表明消息何时移到死信队列,而不是消息最初发送的时间。例如,假设一个消息在被移到死信队列之前,在原始队列中呆了1天。如果死信队列的保留期是4天,那么该消息在3天后从死信队列中被删除,而AroundimateAgeOfOldestMessage是3天。因此,最好的做法是总是将死信队列的保留期设置为比原始队列的保留期长。
因为Amazon SQS是一个分布式系统,即使Amazon SQS在成功返回ReceiveMessage API方法时将消息标记为已交付,消费者也有可能没有收到消息。在这种情况下,Amazon SQS至少记录了一次消息的交付,尽管消费者从未收到过它。因为在这种情况下不会有额外的尝试来传递消息,所以我们不建议将死信队列的最大接收次数设置为1。
在实现请求-响应或远程过程调用(RPC)系统时,请记住以下最佳做法。
不要为每个消息创建回复队列。相反,在启动时为每个生产者创建回复队列,并使用相关的ID消息属性将回复映射到请求。
不要让你的生产者共享回复队列。这可能导致一个生产者收到为另一个生产者准备的响应消息。
关于使用临时队列客户端实现请求-响应模式的更多信息,请参阅请求-响应消息传递模式(虚拟队列)。