Nginx异常捕获:小问题不放大,省下大笔运维费

公司网站突然打不开,客服电话被打爆,老板急得团团转。一查日志,原来是Nginx后端服务挂了,但没人第一时间收到通知。等发现时,已经 downtime 半小时,损失好几万。这种情况其实完全可以避免,关键就在“异常捕获”四个字。

别让5分钟的小故障拖成半天停摆

很多人以为Nginx只是个静态服务器,出点错重启就行。可现实中,一个404没处理好,可能让用户流失;一次502错误堆积,能压垮整个促销活动。与其事后花高价请人救火,不如提前把异常盯住。

用error_page精准拦截常见错误

Nginx自带的error_page指令就是第一道防线。比如用户访问不存在的页面,返回个友好提示,而不是冷冰冰的404白页。

location / {
    error_page 404 = @custom_404;
}

location @custom_404 {
    proxy_pass http://backend/error.html;
}

这样既能留住用户,又能通过日志记录哪些页面常被访问却不存在,顺带优化SEO。

502、504才是真正的“省钱重点”

后端服务超时或崩溃,Nginx会返回502或504。这时候如果直接暴露给用户,体验极差。更聪明的做法是自动重试+降级响应。

location /api/ {
    proxy_pass http://backend;
    proxy_next_upstream error timeout http_502;
    proxy_next_upstream_tries 2;
    
    error_page 502 504 = @fallback;
}

location @fallback {
    add_header Content-Type 'application/json';
    return 200 '{"code": 502, "msg": "服务繁忙,请稍后再试"}';
}

这样一来,哪怕后端抖一下,前端也能平稳过渡,避免用户反复刷新加重压力。

日志加点料,排查快十倍

默认的access.log信息有限。加几个变量,能让异常定位快得多。

log_format detailed '$remote_addr - $remote_user [$time_local] '
                   '"$request" $status $body_bytes_sent '
                   '"$http_referer" "$http_user_agent" '
                   '$request_time $upstream_response_time $upstream_status';

access_log /var/log/nginx/access.log detailed;

特别是$request_time和$upstream_response_time,一眼看出是Nginx慢还是后端慢。省下请专家调优的钱。

配合脚本监控,异常自动报警

光有日志不够,得有人看。写个简单脚本定时扫描错误日志,发现高频50x就发微信或邮件。

#!/bin/bash
COUNT=$(grep 'HTTP/1.1" 50[0-9]' /var/log/nginx/access.log | tail -200 | wc -l)
if [ $COUNT -gt 10 ]; then
    curl -s \
    "https://push.example.com/send?text=Nginx异常增多:$COUNT次"
fi

这种脚本几分钟就能写好,比买商业监控工具便宜多了。

很多团队总想着上大系统、堆中间件,其实把Nginx这层用好,80%的常见问题都能在前端化解。省下的不只是钱,更是反应时间。”}