Spring Cloud SQS ON_SUCCESS删除策略是否会引发死循环及是否有重试机制?
问题答复
1. ON_SUCCESS删除策略会引发无限循环吗?
会存在触发无限循环的潜在可能,原理如下:ON_SUCCESS删除策略的逻辑是:只有你标注@SqsListener的方法正常执行完成、没有抛出任何异常时,框架才会主动调用SQS的DeleteMessage接口将这条消息从队列中删除。
如果方法执行抛出异常,消息不会被删除,等你SQS队列配置的可见性超时时间(Visibility Timeout) 到期后,消息会重新变回可接收状态,监听器会再次拉取到这条消息。如果某条消息每次处理都会确定性抛出异常,没有任何额外限制的话,就会出现「拉取-处理失败-重新入队」的无限循环。
2. 内置的重试防范机制
Spring Cloud AWS SQS提供了两层内置机制来避免死循环,同时需要搭配SQS服务端配置共同生效:
- 客户端本地重试:默认情况下,框架拉取到单条消息后,如果处理抛出异常,会先在本地进行重试,默认最大重试次数为3次,你可以通过配置调整这个阈值,本地重试全程在当前消息的可见性窗口内完成,不会触发消息重新入队。
- 服务端死信队列(DLQ)兜底:客户端重试全部失败后,消息还是会在可见性超时后重新入队,这时需要你在SQS控制台/配置中为原队列绑定死信队列,同时设置
maxReceiveCount参数(比如设置为5):当同一条消息的被拉取次数达到这个阈值还没被成功删除时,SQS服务端会自动将这条消息转移到死信队列,不再投递给原队列,从根本上避免无限循环。
注意:如果你没有为队列配置死信队列,就算启用了客户端本地重试,还是会出现无限循环的问题,生产环境使用
ON_SUCCESS策略时必须搭配死信队列使用。
配置示例
你可以通过如下配置调整客户端重试次数:
spring: cloud: aws: sqs: listener: max-attempts: 5 # 本地最大重试次数,默认3次 backoff: delay: 1000 # 重试间隔时间,单位毫秒
内容的提问来源于stack exchange,提问作者borjab。
相关产品推荐
相关产品推荐

