如何调试引发Ruby应用服务器CPU占满故障的代码?
这种毫无预兆的周期性故障真的让人头大,尤其是没做过代码变更就炸了8台服务器,结合你用Passenger和刚建新CentOS服务器的情况,给你整理几个实战过的排查方向:
核心排查方向
1. 系统层面的周期性任务或资源累积问题
- 先查定时任务:执行
crontab -l(要查所有用户的,比如sudo crontab -u root -l),有没有每隔4个月左右触发的脚本、日志清理或归档任务?有些写得粗糙的脚本可能突然占用大量CPU,甚至引发死循环。 - 检查系统服务的周期行为:比如
logrotate的配置(路径/etc/logrotate.d/),会不会在特定周期执行时出现锁冲突或异常?还有yum自动更新任务,有没有可能在这个时间点触发,导致资源竞争? - 排查资源泄漏:虽然表现是CPU飙升,但很多时候是内存/文件句柄泄漏到阈值后引发的连锁反应。用
top或htop盯着Passenger worker进程,看内存是不是持续增长;也可以用lsof -p <进程ID>统计文件句柄数量,有没有一直涨不回落的情况。
2. Passenger自身的配置与长期运行问题
- 调整worker进程生命周期:Passenger的worker进程如果长期运行(比如4个月),很可能积累内存泄漏或状态异常。试试配置
PassengerMaxRequests,让worker处理一定请求后自动重启,比如在nginx配置里加PassengerMaxRequests 10000,避免单个进程“服役”太久。 - 深挖Passenger日志:日志一般在
/var/log/passenger/或者你的应用日志目录,故障发生时的日志里大概率有线索——比如某个请求卡住导致线程阻塞,进而引发CPU满负载,甚至能找到具体的异常堆栈。 - 测试新服务器隔离验证:你刚建了新的CentOS服务器,把它从负载均衡里摘出来单独跑,观察会不会在同样周期出问题。如果新服务器没事,那大概率是老服务器的系统环境有累积问题(比如旧内核、依赖库版本兼容问题)。
3. 硬件/虚拟化层面的隐性问题
- 查云服务商维护记录:如果是云服务器,去控制台看看故障时间点有没有宿主机迁移、硬件维护的事件——有些云厂商的底层操作会导致服务器出现短暂或持续的CPU异常。
- 分析CPU使用细节:用
mpstat 1 5实时查看CPU的用户态(us)、系统态(sy)占用比例。如果是系统态占比高,可能是内核或驱动问题;用户态高的话还是聚焦到应用或Passenger本身。
临时应急与日志留存
如果再次炸机,先执行passenger-config restart-app /path/to/your/app快速恢复服务,同时立刻抓故障快照:
# 保存top进程信息 top -b -n 1 > top_failure_$(date +%Y%m%d).log # 保存Passenger状态 passenger-status > passenger_status_$(date +%Y%m%d).log # 保存进程栈信息(替换成故障worker的PID) pstack 1234 > pstack_failure_$(date +%Y%m%d).log
这些日志能帮你精准定位到是哪个线程、哪个函数在“吃”CPU。
内容的提问来源于stack exchange,提问作者Sean
相关产品推荐
相关产品推荐

