一聚教程网:一个值得你收藏的教程网站

最新下载

热门教程

Nginx 如何排查 Nginx 性能优化后由于日志写入过于频繁导致的磁盘 IO 瓶颈

时间:2026-09-03 19:27:47 编辑:袖梨 来源:一聚教程网

关键不是“有没有日志”,而是“谁在高频、低效地往磁盘刷数据”:先用iotop-lsof-iostat锁定肇事进程和文件,再检查limit_req_log_level是否仍为error、log_not_found是否开启、client_body_in_file_only是否误启,最后排查logrotate或同盘其他服务(如MySQL)的IO竞争。

排查 Nginx 日志写入引发的磁盘 IO 瓶颈,关键不是“有没有日志”,而是“谁在高频、低效地往磁盘刷数据”。优化后反而出问题,往往说明缓冲没生效、路径没隔离,或误判了瓶颈源头。下面分四步直击要害。

看实时 IO 消耗,锁定真实肇事进程

别只盯 df -htop 的 wa%,那只是症状。用以下组合快速定位:

  1. sudo iotop -o -P:只显示正在做 IO 的进程,按 I/O% 排序,重点找 nginx: worker 进程及其 IO 百分比
  2. sudo lsof -p $PID | grep REG | grep -E "(access|error).log":对高 IO 的 worker PID,确认它正往哪个日志文件写(注意是否还在写已被 logrotate 删除但句柄未释放的 access.log (deleted)
  3. iostat -x 1 3:观察 await(>50ms 就危险)、%util(持续 95%+ 表示磁盘饱和)、avgrq-sz(若长期

验日志配置是否真生效,尤其 buffer 和 flush

很多优化配置写了却没生效,常见于语法错误、上下文错位或模块缺失:

  1. 检查 access_log 行是否带 buffer=64k flush=5s,且不在 if 块或嵌套 location 中(Nginx 不支持条件内启用 buffer)
  2. 运行 nginx -t 确认配置无语法错误;执行 nginx -V 2>&1 | grep -o with-http_gzip_module,确认 gzip 压缩写入可用(如用了 access.log.gz
  3. error_log 是否误配了 debug 级别——该级别需编译时加 --with-debug,否则会静默降级为 warn,但你可能以为它没起作用而反复调大缓冲

查被忽略的“伪优化”日志源

优化常聚焦 access/error,却漏掉三类高频写盘行为:

  1. limit_req_log_level 仍设为 error:每秒上千次限流,就等于每秒上千次强制刷盘。应降为 warnnotice,并单独路由到 /var/log/nginx/limit.log
  2. log_not_found on 未关闭:大量 404 请求(如爬虫扫 favicon.ico)会密集写 error.log。在静态资源 location 块中加 log_not_found off;
  3. client_body_in_file_only on 被意外开启:大 POST 请求体直写磁盘临时文件,与日志无关但共用同一磁盘路径,加剧 IO 竞争

验证磁盘层是否被其他服务拖累

Nginx worker 进入 D 状态,不一定是它自己写的日志导致的:

  1. cat /proc/$PID/stack | grep -E "(blk|ext4|nvme)" 查看卡住的内核调用栈,确认是文件系统层还是块设备层阻塞
  2. 检查 logrotate 是否在整点执行 copytruncate:若日志达数 GB,truncate 操作本身就会触发长时 IO,此时所有 worker 都可能排队等待
  3. 排查同盘其他服务:MySQL 的 innodb_flush_log_at_trx_commit=1、rsync 未限速、PHP session 写 /tmp 小文件,都可能和 Nginx 日志争抢队列

热门栏目