Capistrano部署后如何检测孤立的Sidekiq进程?
这种Sidekiq旧进程残留抢任务的坑我踩过好几次,给你梳理一套从紧急修复到长期预防的方案:
一、紧急修复:干掉残留的旧进程
首先得确认问题确实是旧进程在捣乱:
- 执行命令
ps aux | grep sidekiq,仔细看每个进程的启动时间和工作目录——Capistrano部署的项目,旧进程的工作目录会指向之前的release文件夹,和当前最新的release路径不一样 - 如果开了Sidekiq Web界面,也能直接看到进程的启动时间、版本号,旧进程的版本肯定和当前部署的代码不匹配
确认目标进程后,直接强制终止:
- 找到旧进程的PID,执行
kill -9 <PID>(用-9是防止进程僵死不肯退出) - 再跑一遍
ps aux | grep sidekiq确认旧进程已经消失,这时Redis队列里的任务就只会被最新的Sidekiq进程处理,随机异常应该立刻就消失了
二、修复部署流程:从根源杜绝残留
问题出在Capistrano部署时没正确终止旧Sidekiq进程,得把部署脚本的Sidekiq重启逻辑补扎实:
- 优先用适配Rails 4.2的
capistrano-sidekiqgem,它封装了成熟的停止、启动、重启逻辑,能自动处理多进程、pid文件管理这些细节 - 如果是手动写Capistrano任务,要注意这几点:
- 部署前先调用
sidekiqctl stop <pid文件路径>(默认路径是tmp/pids/sidekiq.pid,多进程模式要遍历所有pid文件) - 加个3-5秒的等待,确保旧进程完全退出后再启动新进程
- 加个校验步骤:启动新进程后,再次检查系统中是否还有指向旧release目录的Sidekiq进程,有就直接杀掉
- 部署前先调用
- 可以在部署完成后的钩子任务里,加一段脚本自动校验所有Sidekiq进程的工作目录,确保全都是当前最新的release路径
三、长期防护:避免再踩同样的坑
- 给Sidekiq启动命令加
--tag参数,比如bundle exec sidekiq --tag production-$(date +%Y%m%d%H%M),这样用ps命令看进程时,一眼就能区分不同部署版本的进程 - 写个定时任务(比如用Whenever gem),每天自动检查一遍Sidekiq进程:如果进程的工作目录不是当前最新的release目录,就自动杀掉
- 偶尔可以用Redis命令
KEYS sidekiq:processes:*查看Sidekiq注册的进程列表,对比系统中实际存在的进程,清理掉已经僵死的进程记录
内容的提问来源于stack exchange,提问作者pragmatic_programmer
相关产品推荐
相关产品推荐

