单实例SQS-Consumer超30条飞行中消息及超时错误排查求助
问题分析与解决建议
飞行中消息过多的核心原因
- SQS预取与消费者默认配置:bbc/sqs-consumer底层调用SQS的
ReceiveMessageAPI时,FIFO队列单次最多能拉取10条消息,哪怕你是逐个处理,库默认的batchSize就是10,这些被拉取的消息都会进入飞行中状态。如果你的消息处理耗时很长(比如Puppeteer加载页面慢),这些消息会一直占着飞行中名额,再加上超时后消息重新入队被再次拉取,数量很容易突破30。 - 可见性超时不匹配处理时长:如果队列的可见性超时设置比你的消息实际处理时间短,SQS会认为这条消息处理失败,把它重新放回队列。这时候之前的那条消息还没处理完(仍在飞行中),新拉取的重复消息又会占用飞行中名额,导致总数飙升。
- 单进程不代表单消息处理:你只跑了一个进程,但sqs-consumer默认会一次拉取多批消息(或者说多单条消息),只要处理没完成,这些消息都会处于飞行中状态。
关于Puppeteer超时与带宽的验证
- t2.medium的带宽瓶颈:t2.medium是突发性能实例,基线带宽只有0.5Gbps,CPU积分用完后带宽会被限制。Puppeteer加载网页会发起大量网络请求,很容易把带宽占满,导致页面加载超时。可以用
iftop命令或者EC2控制台的网络监控面板,查看实时带宽使用率,确认是否达到上限。 - Puppeteer的资源消耗:t2.medium只有2核4G内存,每次启动Chrome实例都会吃掉不少CPU和内存,串行处理时如果前一个页面还没处理完,资源占用高会拖慢后续处理,进而导致消息堆积。可以试试复用Chrome实例(启动一次浏览器,每次处理消息开新页面),或者禁用图片、CSS加载来减少资源消耗。
具体修复步骤
- 调整sqs-consumer配置:
- 显式设置
batchSize: 1,强制每次只拉取1条消息,从根源上减少飞行中消息的数量 - 把队列的
visibilityTimeout设为消息平均处理时间的2倍以上(比如处理一条要30秒,就设60秒),避免消息被提前放回队列 - 保留长轮询(
waitTimeSeconds设为20),但配合batchSize:1,减少空轮询的同时控制拉取量
- 显式设置
- 优化消息处理逻辑:
- 给Puppeteer的页面操作加超时捕获,超时后主动调用
deleteMessage删除消息(如果确定无法处理),或者延长可见性超时,避免消息反复入队 - 复用Chrome实例:在消费者启动时初始化一个浏览器对象,每次处理消息只创建新页面,处理完关闭页面,不要关闭浏览器,减少资源开销
- 给Puppeteer的页面操作加超时捕获,超时后主动调用
- 监控EC2资源状态:
- 查看EC2控制台的CPU积分、CPU使用率、内存和带宽数据,确认是不是资源瓶颈导致处理缓慢
- 如果是CPU积分不够,换成t3.medium(无突发限制)或者升级到更大的实例规格,从硬件层面解决问题
内容的提问来源于stack exchange,提问作者mikejackowski
相关产品推荐
相关产品推荐

