记录一下那天晚上的排查过程。一台 2 核 4G 的轻量服务器跑 WordPress,/var/log/nginx 下 access.log 一小时涨八 G,按路径统计九成是 GET /wp-login.php 和随机 .php 文件名,返回全是四零四,磁盘两天就告警。
刚开始盯着「入口没做频率限制,请求全落到 PHP 上才返回四零四,白耗 CPU 又白写日志」,折腾了半个多小时,排掉了。
真正麻烦的地方在于,几个原因的现象几乎一样。扫描器照字典遍历路径,每个四零四都要写一行 access 日志,日志量与实际流量一比一。还有一种是log_format 里带了 user_agent 与 request_body,单条日志被撑到几 KB,条数一多就成倍放大。
不容易想到的是,logrotate 一天切一次,单日文件几十 G,切割时压缩把 CPU 也吃满。
量化到底哪类请求在刷
awk '{print $7}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -10
再往下在入口按来源地址限速,挡住高频扫描
sed -i '/http {/a\ limit_req_zone $binary_remote_addr zone=scan:10m rate=10r/s;' /etc/nginx/nginx.conf && nginx -t
不存在的 php 文件直接返回四零四,别交给后端
sed -i 's#location ~ \.php$ {#location ~ \.php$ { try_files $uri =404;#' /etc/nginx/conf.d/site.conf && nginx -t
末了把已经写大的日志切走并重新打开句柄
mv /var/log/nginx/access.log /var/log/nginx/access.log.old && nginx -s reopen && gzip -1 /var/log/nginx/access.log.old
别只看报错消失,验证要多做一步。一小时后再看日志增量落到一百 M 以内,四四四与四零四的比例明显上升,磁盘可用空间不再以 G 为单位下降。
限速阈值要按真实业务量定,压得太狠会把正常用户一起挡在门外,先在日志上算一遍峰值再动手。线上能稳定复现的问题都不算难,难的是只在大流量下才出现的那种。
