Elastic Beanstalk环境中@SqsListener无法接收SQS消息
问题情况
本地运行Spring Boot WAR项目时,加了@SqsListener注解的方法能正常从SQS队列拉取消息,但部署到Elastic Beanstalk的Web环境后,该方法完全接收不到消息。已确认EC2角色的SQS权限配置正确。
相关代码
监听方法:
@SqsListener(value = "rishi-demo-queue", deletionPolicy = SqsMessageDeletionPolicy.ON_SUCCESS) public void getSqsMessage(String message) { logger.info("inside sqs listener, message: {}",message); }
已验证的SQS队列策略:
{ "Version": "2008-10-17", "Id": "__default_policy_ID", "Statement": [ { "Sid": "__owner_statement", "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam::<accountid>:root" }, "Action": "SQS:*", "Resource": "arn:aws:sqs:ap-south-1:<accountid>:rishi-demo-queue" }, { "Sid": "__EC2_statement", "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam::<accountid>:role/aws-elasticbeanstalk-ec2-role" }, "Action": "SQS:*", "Resource": "arn:aws:sqs:ap-south-1:<accountid>:rishi-demo-queue" } ] }
排查和解决步骤
1. 先检查Spring Boot启动类配置
WAR包部署到Web容器时,默认不会自动启动Spring的异步监听容器。必须确保启动类继承SpringBootServletInitializer,并正确重写configure方法,同时别忘了添加@EnableSqs注解开启SQS监听:
@SpringBootApplication @EnableSqs // 必须添加此注解,否则SQS监听功能不会激活 public class DemoApplication extends SpringBootServletInitializer { @Override protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { return application.sources(DemoApplication.class); } public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); } }
2. 再确认Elastic Beanstalk的IAM角色权限
虽然队列策略已配置,但要检查EC2实例关联的aws-elasticbeanstalk-ec2-role是否绑定了实例配置文件,且该实例配置文件的权限策略允许SQS相关操作:
- 进入IAM控制台,找到
aws-elasticbeanstalk-ec2-role,检查其权限策略是否包含:
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "sqs:ReceiveMessage", "sqs:DeleteMessage", "sqs:GetQueueAttributes" ], "Resource": "arn:aws:sqs:ap-south-1:<accountid>:rishi-demo-queue" } ] }
队列策略是资源端的权限控制,实例角色的权限策略是身份端的控制,两者必须同时配置正确才能生效。
3. 查看Web容器启动日志
Elastic Beanstalk默认使用Tomcat作为容器,部署WAR包后可以查看EB环境的日志(路径为/var/log/tomcat9/catalina.out),确认是否有SQS监听容器启动的日志,比如:
Started SqsListenerEndpointContainer for [com.example.demo.SqsListenerBean.getSqsMessage(String)]
如果没有这类日志,说明监听容器未启动,大概率是启动类配置问题。
4. 确认区域配置
本地运行时可能通过AWS配置文件或环境变量指定了ap-south-1区域,但部署到EB后需要确保环境变量中设置了AWS_REGION=ap-south-1,或者在Spring配置文件(application.properties/application.yml)中明确配置:
cloud.aws.region.static=ap-south-1 cloud.aws.stack.auto=false
避免因区域不匹配导致无法找到目标队列。
5. 尝试使用队列完整URL
如果队列名称不是全局唯一的,或者存在区域差异,直接将队列的完整URL填入@SqsListener的value值,比如:
@SqsListener(value = "https://sqs.ap-south-1.amazonaws.com/<accountid>/rishi-demo-queue", deletionPolicy = SqsMessageDeletionPolicy.ON_SUCCESS)
确保Spring能精准定位到目标队列。
总结
优先排查启动类的@EnableSqs注解和SpringBootServletInitializer继承配置,其次确认IAM实例角色的权限策略,最后检查区域配置和队列定位是否正确。通过EB的日志可以快速判断监听容器是否启动,以及是否存在权限或连接错误。
内容的提问来源于stack exchange,提问作者Rishiraj Fasalkar

