先确认磁盘i/o是否为瓶颈:用iostat -x 1查%util>80%且%await>50ms,top看iowait>20%,iotop -o定位高写nginx worker;再通过lsof -p $pid查access.log、error.log、proxy_temp等路径及(deleted)句柄;检查日志buffer/flush配置、error_log级别、静态资源日志开关、logrotate copytruncate;最后排查proxy_buffering、fastcgi临时文件、client_body缓冲及temp目录存储介质。

直接看 iowait 和日志落盘行为,重点锁定写操作来源和缓冲状态。
确认磁盘 I/O 是否真为瓶颈
先用系统工具验证是否是磁盘拖慢了 Nginx:
- 运行 iostat -x 1,观察 %util 是否持续高于 80%,%await 是否显著升高(如 >50ms),这两个指标同时异常说明磁盘已饱和
- 执行 top,看 CPU 行的 iowait 是否长期超过 20%;若接近或超过 50%,基本可判定 I/O 是主因
- 用 iotop -o 找出具体哪个进程在大量写盘,如果看到多个 nginx worker 的 WRITE 占比极高,就指向日志或临时文件写入问题
定位 Nginx 写盘的具体路径
光知道是 Nginx 不够,得知道它在往哪写、为什么写:
- 挑一个高 IO 的 worker 进程 PID,执行 lsof -p $PID,重点关注打开的文件:/var/log/nginx/access.log、error.log、proxy_temp/、fastcgi_temp/、client_body_temp/ 等路径
- 若发现大量 (deleted) 文件句柄(
lsof | grep deleted),说明日志或临时文件被轮转后未释放,Nginx 仍在往已删文件写入,持续占用空间和 I/O - 检查是否启用了 client_body_in_file_only on 或大文件上传场景,这会让请求体直写磁盘而非内存缓冲
检查日志配置是否加剧 I/O 压力
默认日志行为极易引发高频小写,需逐项核对:
- 查看 access_log 是否启用 buffer 和 flush:
access_log /path/to/log main buffer=64k flush=5s;—— 若 buffer=0 或没设 buffer,就是每请求落盘一次 - error_log 不支持缓冲,确认级别是否为 warn 或 error;若设为 info/debug,尤其在 proxy_pass 或 SSL 场景下,会生成海量日志
- 静态资源(.js/.css/.png)和健康检查接口(如 /healthz)是否仍开启日志?应统一加
access_log off; - logrotate 是否配置了
copytruncate?否则重命名日志时可能阻塞 worker 写入
排除非日志类磁盘写入干扰
别只盯着 access.log,Nginx 的其他写盘行为同样致命:
- 检查 proxy_buffering on 是否开启,若后端响应大且未及时消费,Nginx 会把响应体写入 proxy_temp 目录
- fastcgi/uwsgi/scgi 协议有独立临时文件机制,确认
fastcgi_max_temp_file_size和fastcgi_buffer_size是否过小,导致频繁刷盘 - 确认
client_max_body_size和client_body_buffer_size设置是否合理;过小会迫使 body 落盘,过大则内存压力上升 - 临时目录(如 proxy_temp)是否落在机械盘或 NFS 上?建议迁移到 SSD 或内存盘(如
proxy_temp_path /dev/shm/nginx/proxy_temp;)











