生产环境Sidekiq性能异常:CPU占用过高及多进程显示问题求助
Sidekiq性能优化方案(双核服务器场景)
问题核心梳理
- 双核服务器配置下,Sidekiq单进程+8线程的设定,理论上应仅占用单核心,但实际线程跨核心运行,与Puma抢占CPU资源
- 1.5万条邮件任务调度叠加用户访问时,CPU直接拉满,导致Puma无法处理请求
- htop显示的9个"进程"是Sidekiq主进程+8工作线程的可视化展示,与
ps aux、Sidekiq面板的结果一致
具体优化配置
1. 降低Sidekiq并发数,减少上下文切换
默认concurrency=8对于双核服务器来说过高,线程间频繁切换会额外消耗CPU。建议将并发数调整为4-6,给Puma预留足够的CPU资源:
修改config/sidekiq.yml:
concurrency: 4
或者启动时直接指定:
bundle exec sidekiq -c 4
2. 强制CPU核心绑定,隔离资源
用taskset命令将Sidekiq和Puma分别绑定到不同核心,彻底避免资源抢占:
- 启动Sidekiq时绑定到核心0:
taskset -c 0 bundle exec sidekiq -c 6
- 启动Puma时绑定到核心1:
taskset -c 1 bundle exec puma -C config/puma.rb
3. 分批调度邮件任务,降低瞬时负载
一次性入队1.5万条任务会瞬间占满Sidekiq线程,导致CPU冲高。建议拆分批次入队,控制瞬时压力:
# 按100条为一批,间隔10秒入队 User.pluck(:email).each_slice(100) do |email_batch| email_batch.each { |email| SendEmailJob.perform_async(email) } sleep(10) end
也可以用Sidekiq批量入队API,更高效地控制批次:
email_batches = User.pluck(:email).each_slice(100).to_a Sidekiq::Client.push_bulk('class' => SendEmailJob, 'args' => email_batches)
4. 调整任务与进程优先级
- 给邮件任务设置较低优先级,让Puma的请求处理获得更高调度权重:
class SendEmailJob include Sidekiq::Job sidekiq_options queue: :mailers, priority: 5 # 数值越大优先级越低,默认0为最高 end
- 用
renice命令调整进程优先级,进一步偏向Puma:
# 降低Sidekiq进程优先级(数值越大优先级越低) renice +5 -p $(pgrep -f sidekiq) # 提高Puma进程优先级 renice -5 -p $(pgrep -f puma)
5. 优化邮件发送逻辑
邮件渲染和发送可能是CPU/IO瓶颈,可从以下方向优化:
- 预渲染邮件模板并缓存,避免重复渲染消耗CPU
- 使用第三方邮件服务API替代本地SMTP,减少本地处理负载
- 开启Sidekiq死信队列,避免失败任务反复重试占用资源:
# config/sidekiq.yml dead: true dead_max_jobs: 1000
验证指标
调整后通过htop监控CPU使用率,确保Sidekiq+Puma的总占用不超过90%;同时跟踪Puma的请求响应时间,确认用户访问无延迟。
内容的提问来源于stack exchange,提问作者Javier Rodríguez
相关产品推荐
相关产品推荐

