使用amazon-sqs-java-messaging-lib与@JmsListener启动时接收2条消息问题
解决amazon-sqs-java-messaging-lib启动自动接收2条消息的问题
我之前也碰到过类似的情况,结合对Spring JMS和Amazon SQS Java Messaging Lib的实际使用经验,给你几个排查和解决的方向:
首先,先排除最直观的可能性:
- 检查SQS队列的遗留消息:登录AWS控制台找到你的目标队列,看看「Messages Available」的数量是不是刚好是2条。如果是的话,这些就是之前没被正确处理或清理的消息,服务启动时Listener容器会自动拉取这些待处理消息。你可以先手动删除这些测试/遗留消息,再重启服务验证问题是否消失。
如果队列本身是空的,那问题大概率出在Listener容器的配置上,你可以调整以下参数:
- 限制并发消费者与消息获取量:默认的
DefaultJmsListenerContainerFactory可能会有一些默认配置导致启动时拉取多条消息。你可以在配置Bean时明确设置并发数和单次获取的最大消息数:
@Bean public DefaultJmsListenerContainerFactory jmsListenerContainerFactory(SQSConnectionFactory connectionFactory) { DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory(); factory.setConnectionFactory(connectionFactory); // 设置并发消费者为1,避免多实例同时拉取消息 factory.setConcurrency("1"); // 限制每次任务最多获取1条消息 factory.setMaxMessagesPerTask(1); // 设置接收超时,避免启动时无限制等待拉取 factory.setReceiveTimeout(1000L); return factory; }
- 确认消息处理的ACK模式:如果你的消息处理逻辑没有正确完成确认,可能会导致消息被重新放回队列,进而在启动时被再次拉取。你可以显式设置会话确认模式,并在Listener方法中手动确认:
// 在容器工厂中设置确认模式 factory.setSessionAcknowledgeMode(Session.CLIENT_ACKNOWLEDGE);
然后在你的Listener方法里手动确认消息:
@JmsListener(destination = "your-target-queue") public void processMessage(Message message) throws JMSException { // 这里写你的消息处理逻辑 // 处理完成后手动确认 message.acknowledge(); }
另外还要注意:如果你的服务之前异常退出,SQS里的消息可能因为没有被确认而重新变为可用状态,这也会导致启动时被拉取。建议确保你的消息处理逻辑是幂等的,即使重复消费也不会出现业务问题。
内容的提问来源于stack exchange,提问作者Dmytro Kozhemiakin
相关产品推荐
相关产品推荐

