定位思路与关键日志
- 先明确并发问题的表现:是吞吐上不去、响应变慢、还是502/504增多。对应查看:
- Nginx access.log:关注请求耗时字段,如**$request_time**、$upstream_response_time,用于识别慢请求与上游瓶颈。
- Nginx error.log:出现upstream prematurely closed connection或connect() failed多与后端处理能力不足或超时有关。
- PHP-FPM error.log:出现WARNING: [pool www] server reached max_children说明并发超出进程池上限;出现WARNING: [pool www] child X, script ‘…’ execution timed out提示脚本超时或阻塞。
- PHP-FPM slowlog:定位具体脚本与函数/SQL的耗时点,是并发下性能劣化的首要线索。
- MySQL slow query log:当上游慢或502增多时,联动排查慢SQL与索引缺失。
常见并发问题与日志特征
| 现象 |
日志特征 |
可能根因 |
快速验证 |
| 吞吐上不去、响应变慢 |
Nginx 中大量请求**$request_time或$upstream_response_time偏高;FPM 进程数接近pm.max_children** |
进程池过小、慢脚本/慢SQL、外部依赖阻塞 |
同时查看 FPM 进程数与 slowlog;抓取慢SQL |
| 502/504 增多 |
Nginx error.log 报upstream prematurely closed;FPM 报max_children或request_terminate_timeout触发 |
后端处理不过来、超时过短、进程崩溃/重启 |
提高 FPM 上限与超时阈值,观察是否缓解 |
| 日志错乱/丢失、磁盘 IO 高 |
多进程写同一日志导致顺序错乱/内容缺失;磁盘繁忙 |
同步写文件、无缓冲/轮转 |
改为异步/缓冲写、启用logrotate轮转 |
| 偶发“脚本中断” |
FPM 报execution timed out或child exited on signal |
超时设置过短、致命错误、内存不足 |
调整request_terminate_timeout、检查内存与错误日志 |
上述特征与处置要点可结合 FPM 进程池设置、慢日志与 Nginx 耗时字段联动确认。
从日志到配置的闭环优化
- 计算并调整 FPM 进程池
- 估算单进程内存(框架应用常见50–80MB/进程),按“可用内存×0.8 ÷ 单进程内存”设定pm.max_children,避免 OOM。
- 动态模式推荐:pm.start_servers ≈ CPU核数×1~2、min_spare_servers与max_spare_servers围绕核数设置;设置pm.max_requests定期回收进程,缓解内存泄漏。
- 超时与慢日志联动
- 将request_slowlog_timeout设为1–5s,捕获长耗时函数/SQL;结合request_terminate_timeout与 Nginx 的fastcgi_read_timeout/fastcgi_send_timeout协调,避免过早中断或堆积。
- Web 服务器日志增强
- Nginx 自定义log_format记录**$request_time与$upstream_response_time**,便于量化并发下的耗时分布与上游瓶颈。
- 应用日志治理
- 降低日志级别、减少冗余;采用异步/缓冲写(如Monolog的异步处理)降低同步写文件对请求路径的影响;使用logrotate按日轮转并压缩,控制磁盘与 I/O。
命令与配置示例
- 实时观察与定位
- 实时看 FPM 错误与进程告警:tail -f /var/log/php-fpm/error.log
- 统计 Nginx 中耗时超过3秒的请求:awk ‘($NF > 3)’ /var/log/nginx/access.log
- 统计 Top 10 高频 URI:grep “GET” /var/log/nginx/access.log | cut -d" " -f7 | sort | uniq -c | sort -nr | head -10
- 查看 FPM 慢日志中脚本分布:cat /var/log/php-fpm/slow.log | awk ‘{print $1}’ | sort | uniq -c | sort -nr
- FPM 进程池关键配置(示例)
- [www]
- pm = dynamic
- pm.max_children = 400
- pm.start_servers = 50
- pm.min_spare_servers = 30
- pm.max_spare_servers = 100
- pm.max_requests = 500
- request_slowlog_timeout = 1s
- slowlog = /var/log/php-fpm/slow.log
- Nginx 日志格式与慢请求标记(示例)
- log_format main ‘$remote_addr - $remote_user [$time_local] “$request” $status $body_bytes_sent “$http_referer” “$http_user_agent” rt=$request_time uct=“$upstream_connect_time” uht=“$upstream_header_time” urt=“$upstream_response_time”’;
- 使用 map 将**$request_time > 1s**的请求写入慢日志(高级用法)。
压测与持续监控
- 基线压测:使用wrk进行并发基线测试(如:wrk -t32 -c1000 -d30s http://your-site.com/),观察成功率、P95/P99 延迟与错误率,验证配置调整成效。
- 运行期观测:持续关注FPM 进程数、内存占用、队列堆积与慢日志命中,按“小步调整、每次观察≥10分钟”的节奏收敛到稳定配置。