Cronjob执行时网站卡顿的问题排查与优化求助
问题分析
当前核心矛盾:为实现PHP脚本B每5秒执行一次,通过Cronjob每分钟发起12次curl调用,虽B做了异步处理,但切换到64vCPU虚拟机后反而出现网站卡顿。结合现象判断,问题并非CPU核心数不足,而是连接资源耗尽、Web服务器配置不匹配、进程调度策略或调用方式不合理导致。
解决方案
1. 优化Cron调用方式,避免瞬间请求风暴
若当前Cronjob是串行发起12次curl,会导致Cron进程长时间占用且请求集中;若并行发起,瞬间12个HTTP请求可能打满Web服务器连接配额。建议改成后台异步发起+间隔延迟的shell脚本:
#!/bin/bash # 每分钟执行一次,间隔5秒发起调用,每个curl后台执行 for i in {1..12}; do # 关闭Keep-Alive,避免占用长连接资源 curl -s -H "Connection: close" "http://your-domain/B.php" & sleep 5 done
既保证5秒间隔,又不会让Cron进程阻塞,同时分散请求压力。
2. 调整Litespeed关键配置(不止Worker数量)
- 调高连接数限制:在Litespeed控制台
Server Configuration > Tuning中,将全局或对应虚拟主机的Max Connections调高(如设为100),避免瞬间请求触发连接上限导致排队。 - 优化PHP LSAPI参数:在
Server Configuration > External App > PHP配置里,调整PHP Max Children(建议设为32-64,匹配CPU核心数)、Max Request(如设为1000),避免PHP进程不足引发请求阻塞;同时启用Graceful Restart,减少进程重启带来的波动。 - 强制关闭长连接:针对Cron的curl请求,添加
-H "Connection: close"参数,释放Web服务器长连接资源给用户请求。
3. 简化PHP B的异步实现,彻底释放连接
当前异步代码依赖手动flush,在Litespeed环境下,用fastcgi_finish_request()能更可靠断开HTTP连接,立刻释放Web服务器资源:
ignore_user_abort(true); set_time_limit(0); // 直接返回202响应,无需多余缓冲操作 header($_SERVER["SERVER_PROTOCOL"] . " 202 Accepted"); header("Content-Length: 0"); header("Connection: close"); // 强制完成请求,释放Web服务器连接 if (function_exists('fastcgi_finish_request')) { fastcgi_finish_request(); } // 后续执行业务逻辑 // ...
4. 重构执行逻辑,减少HTTP请求次数
既然Cron最小间隔为1分钟,可让PHP B自行承担循环任务,Cron每分钟仅调用一次B即可:
ignore_user_abort(true); set_time_limit(0); // 先返回响应,释放连接 header($_SERVER["SERVER_PROTOCOL"] . " 202 Accepted"); header("Content-Length: 0"); header("Connection: close"); if (function_exists('fastcgi_finish_request')) { fastcgi_finish_request(); } // 循环12次,每次执行后休眠5秒 for ($loop = 0; $loop < 12; $loop++) { // 执行业务逻辑 run_business_task(); // 最后一次循环无需休眠 if ($loop < 11) { sleep(5); } }
彻底避免每分钟12次HTTP请求,大幅降低Web服务器负载。
5. 排查服务商B的虚拟机底层问题
- 用
top、iostat工具在Cron执行时监控:- 查看CPU使用率是否瞬间飙升(若为共享CPU,可能因超售导致调度延迟)
- 检查磁盘IO(
iostat -x 1),若%util接近100%,说明磁盘性能差,业务逻辑中的IO操作会阻塞进程 - 查看内存是否用到swap(
free -m),swap交换会引发严重卡顿
- 联系服务商确认虚拟机的CPU调度优先级、磁盘类型(是否为SSD),是否存在隐性资源限制。
内容的提问来源于stack exchange,提问作者iristhennars
相关产品推荐
相关产品推荐

