Sidekiq多进程下无法拾取队列任务的问题排查咨询
调试Sidekiq进程挂起问题的步骤
1. 排查资源瓶颈
- 监控容器与宿主机资源:用
docker stats查看Sidekiq/Puma容器的CPU、内存使用率;宿主机用htop看整体负载,iostat检查磁盘IO是否饱和,ss -s统计TCP连接数是否超限。 - 检查Redis状态:执行
redis-cli info stats查看连接数、阻塞客户端数量;用redis-cli slowlog get 10排查是否存在慢查询命令,这类命令可能导致Sidekiq线程长时间阻塞。
2. 分析Sidekiq进程与日志
- 开启调试日志:启动Sidekiq时添加
--verbose参数,或在配置文件中设置log_level: :debug,追踪任务执行的每一步,看是否有未捕获的异常或执行卡点。 - 查看进程状态:用
ps aux | grep sidekiq检查进程状态,若出现D(不可中断睡眠),通常是IO阻塞导致;用rbspy record -p <sidekiq_pid>抓取线程调用栈,定位线程卡住的具体代码位置。
3. 验证任务代码的并发兼容性
- 复现任务孤立场景:将业务任务代码单独抽出,用多线程/多进程批量执行(比如用Ruby的
Thread循环或fork创建进程),看是否会出现挂起。 - 检查阻塞操作:任务中是否存在未设置超时的数据库查询、HTTP请求、文件IO?比如数据库连接池耗尽导致线程等待连接,或无超时的外部调用导致线程永久挂起。
- 排查资源竞争:检查任务是否使用全局变量、未同步的共享资源,这类场景可能引发死锁。
4. 核对Docker与宿主机限制
- 检查容器资源配额:确认Docker是否给Sidekiq/Puma容器设置了
--cpus、--memory限制,若CPU配额不足,进程可能因调度频繁出现假死。 - 调整系统ulimit:执行
ulimit -n查看打开文件数限制,Sidekiq、Puma加Redis连接可能超出默认值,导致无法建立新连接;可临时用ulimit -n 65535调高,或在系统配置中永久修改。 - 检查内核参数:核对
net.core.somaxconn(TCP监听队列大小)、vm.max_map_count(内存映射限制)是否满足高并发需求,不足时需调整内核配置。
5. 逐步缩小复现范围
- 隔离Puma影响:保持12个Sidekiq进程,逐步减少Puma进程数(比如先降到20,再10),排查是否是两类进程的资源竞争导致问题。
- 替换测试任务:用极简任务(仅打印日志)替代业务任务,若12个Sidekiq进程可正常运行,说明问题出在业务代码;若仍挂起,则聚焦环境或Sidekiq配置。
- 升级Sidekiq版本:若使用旧版本,可能存在已知并发bug,升级到最新稳定版验证是否解决问题。
内容的提问来源于stack exchange,提问作者Aakash Khandelwal
相关产品推荐
相关产品推荐

