Nginx 作为高性能的 Web 服务器和反向代理服务器,在处理请求时可能会返回各种 HTTP 错误码。理解这些错误码的含义、产生原因和解决方法,对于运维和故障排查至关重要。
Nginx HTTP错误码概述 HTTP 状态码由三位数字组成,分为五个类别:
graph TB
A[HTTP状态码] --> B[1xx 信息性]
A --> C[2xx 成功]
A --> D[3xx 重定向]
A --> E[4xx 客户端错误]
A --> F[5xx 服务器错误]
B --> B1[100 Continue 101 Switching Protocols]
C --> C1[200 OK 201 Created 204 No Content]
D --> D1[301 Moved Permanently 302 Found 304 Not Modified]
E --> E1[400 Bad Request 403 Forbidden 404 Not Found]
F --> F1[500 Internal Server Error 502 Bad Gateway 504 Gateway Timeout]
style B fill:#74C0FC
style C fill:#51CF66
style D fill:#FFD43B
style E fill:#FF6B6B
style F fill:#FF8787
4xx 客户端错误(常见) 400 Bad Request 含义 :请求语法错误,服务器无法理解。
常见原因
请求头格式错误
请求体过大(超过 client_max_body_size)
Cookie 过大
URL 编码错误
请求方法不支持
解决方案 1 2 3 4 5 6 7 8 9 http { client_max_body_size 10m ; client_body_buffer_size 128k ; client_header_buffer_size 1k ; large_client_header_buffers 4 4k ; }
排查方法 1 2 3 4 5 6 tail -f /var/log/nginx/error.log
401 Unauthorized 含义 :请求需要身份认证。
常见原因
解决方案 1 2 3 4 5 6 7 8 9 10 11 location /protected { auth_basic "Restricted Area" ; auth_basic_user_file /etc/nginx/.htpasswd; } location /api { auth_jwt "Restricted" ; auth_jwt_key_file /etc/nginx/jwt.key; }
403 Forbidden 含义 :服务器理解请求,但拒绝执行。
常见原因
文件权限问题
文件或目录没有读取权限
Nginx 用户没有访问权限
目录索引被禁用
autoindex 未启用,访问目录时返回 403
访问控制
SELinux 限制 (Linux)
解决方案 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 location /files { autoindex on ; autoindex_exact_size off ; autoindex_localtime on ; } chmod 644 /path/to/filechmod 755 /path/to/directory location /admin { allow 192.168.1.0 /24 ; deny all; } getenforce setsebool -P httpd_read_user_content 1
排查方法 1 2 3 4 5 6 7 8 ls -la /path/to/fileps aux | grep nginx ls -Z /path/to/file
404 Not Found 含义 :请求的资源不存在。
常见原因
URL 路径错误
文件被删除或移动
root 或 alias 配置错误
重写规则配置错误
解决方案 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 server { root /var/www/html; index index.html index.htm; location / { try_files $uri $uri / =404 ; } } location /images { alias /var/www/images; } error_page 404 /404 .html;location = /404 .html { root /var/www/html; internal; } location / { try_files $uri $uri / @fallback ; } location @fallback { proxy_pass http://backend; }
排查方法 1 2 3 4 5 6 7 8 ls -la /var/www/html/path/to/filenginx -t tail -f /var/log/nginx/access.log | grep 404
405 Method Not Allowed 含义 :请求方法不被允许。
常见原因
使用了不允许的 HTTP 方法(如 PUT、DELETE)
静态文件服务器不支持某些方法
解决方案 1 2 3 4 5 6 7 8 9 10 11 12 13 location /api { limit_except GET POST { deny all; } } location /api { if ($request_method !~ ^(GET|POST|HEAD)$ ) { return 405 ; } }
408 Request Timeout 含义 :请求超时。
常见原因
客户端发送请求太慢
网络连接问题
client_header_timeout 或 client_body_timeout 设置过短
解决方案 1 2 3 4 5 6 7 8 9 10 http { client_header_timeout 60s ; client_body_timeout 60s ; send_timeout 60s ; keepalive_timeout 65 ; keepalive_requests 100 ; }
413 Request Entity Too Large 含义 :请求实体过大。
常见原因
上传文件超过 client_max_body_size 限制
请求体过大
解决方案 1 2 3 4 5 6 7 8 9 http { client_max_body_size 100m ; location /upload { client_max_body_size 500m ; } }
排查方法
414 Request-URI Too Long 含义 :请求 URI 过长。
常见原因
解决方案 1 2 3 4 http { large_client_header_buffers 4 16k ; }
429 Too Many Requests 含义 :请求过于频繁。
常见原因
解决方案 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 http { limit_req_zone $binary_remote_addr zone=api_limit:10m rate=10r/s; server { location /api { limit_req zone=api_limit burst=20 nodelay; proxy_pass http://backend; } } } error_page 429 /429 .html;location = /429 .html { root /var/www/html; internal; }
499 Client Closed Request 含义 :客户端在服务器返回响应之前关闭了连接。
特点
Nginx 特有错误码 :这是 Nginx 自定义的错误码,不是标准 HTTP 状态码
客户端主动断开 :客户端在等待响应时主动关闭了连接
不记录为标准错误 :通常不会记录到标准错误日志,但会出现在访问日志中
常见原因
客户端超时
客户端设置了较短的超时时间
客户端认为服务器响应太慢,主动取消请求
服务器响应慢
客户端取消操作
用户点击了浏览器的停止按钮
用户关闭了浏览器标签页
移动端应用切换到后台
网络问题
网络不稳定导致连接中断
移动网络切换(WiFi 到 4G)
代理服务器断开连接
负载均衡器超时
解决方案 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 http { client_header_timeout 60s ; client_body_timeout 60s ; proxy_connect_timeout 60s ; proxy_send_timeout 300s ; proxy_read_timeout 300s ; keepalive_timeout 65 ; keepalive_requests 100 ; } location /slow-api { proxy_pass http://backend; proxy_connect_timeout 300s ; proxy_send_timeout 300s ; proxy_read_timeout 300s ; proxy_buffering on ; proxy_buffer_size 4k ; proxy_buffers 8 4k ; proxy_busy_buffers_size 8k ; proxy_ignore_client_abort on ; } location /api { proxy_pass http://backend; proxy_ignore_client_abort on ; } location /long-task { return 202 ; proxy_pass http://backend; proxy_read_timeout 0 ; }
排查方法 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 tail -f /var/log/nginx/access.log | grep " 499 " awk '$9 == 499 {print}' /var/log/nginx/access.log | wc -l awk '$9 == 499 {print $7}' /var/log/nginx/access.log | sort | uniq -c | sort -rn awk '$9 == 499 {print $NF}' /var/log/nginx/access.log | sort -n grep "192.168.1.100.* 499 " /var/log/nginx/access.log tail -f /var/log/nginx/access.log | awk '$9 == 499 {print}'
日志分析示例 1 2 3 4 5 6 7 8 9 10 11 12 awk '$9 == 499 {print $7}' /var/log/nginx/access.log | \ sort | uniq -c | sort -rn | head -10 awk '$9 == 499 {print substr($4, 14, 2)}' /var/log/nginx/access.log | \ sort | uniq -c | sort -n awk '$9 == 499 {print $NF}' /var/log/nginx/access.log | \ awk '{sum+=$1; count++} END {print "平均响应时间:", sum/count, "秒"}'
性能优化建议 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 location /api { proxy_pass http://backend; proxy_cache my_cache; proxy_cache_valid 200 10m ; proxy_cache_key "$scheme $request_method $host $request_uri " ; gzip on ; gzip_types application/json application/javascript; } location /async-task { access_log off ; return 202 "Task accepted" ; } upstream backend { server 127.0.0.1:8080 max_conns=100 ; queue 100 timeout=60s ; } location /api { proxy_pass http://backend; proxy_read_timeout 300s ; }
监控和告警 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 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_connect_time ' ; access_log /var/log/nginx/access.log detailed;map $status $is_499 { 499 1; default 0 ; } access_log /var/log/nginx/499 .log combined if=$is_499 ;
与其他错误码的区别
错误码
含义
触发方
场景
408
请求超时
服务器
服务器等待客户端请求超时
499
客户端关闭连接
客户端
客户端在等待响应时主动断开
502
网关错误
服务器
后端服务不可用或返回无效响应
504
网关超时
服务器
后端服务响应超时
注意事项
不是真正的错误
499 通常表示客户端主动取消,不一定是服务器问题
但如果大量出现,可能表示服务器响应太慢
资源消耗
使用 proxy_ignore_client_abort on 可能导致服务器资源浪费
客户端断开后,服务器仍在处理请求
日志分析
499 错误不会出现在错误日志中,只在访问日志中
需要单独分析访问日志来监控 499 错误
优化方向
重点优化后端响应速度
实现请求队列和异步处理
使用缓存减少后端压力
5xx 服务器错误(常见) 500 Internal Server Error 含义 :服务器内部错误。
常见原因
PHP/Python 等脚本错误
FastCGI 配置错误
PHP-FPM 未运行
FastCGI 超时
缓冲区设置不当
权限问题
资源限制
解决方案 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 location ~ \.php$ { fastcgi_pass 127.0.0.1:9000 ; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root $fastcgi_script_name ; include fastcgi_params; fastcgi_connect_timeout 300 ; fastcgi_send_timeout 300 ; fastcgi_read_timeout 300 ; fastcgi_buffer_size 64k ; fastcgi_buffers 4 64k ; fastcgi_busy_buffers_size 128k ; } error_log /var/log/nginx/error .log warn ;error_page 500 502 503 504 /50x.html;location = /50x.html { root /var/www/html; internal; }
排查方法 1 2 3 4 5 6 7 8 9 10 11 12 13 tail -f /var/log/nginx/error.logtail -f /var/log/php-fpm/error.logsystemctl status php-fpm free -h df -hulimit -a
502 Bad Gateway 含义 :作为网关或代理的服务器,从上游服务器收到无效响应。
常见原因
后端服务未运行
应用服务器(如 Tomcat、Node.js)未启动
PHP-FPM 未运行
后端服务崩溃
连接问题
超时设置过短
proxy_connect_timeout 过短
后端响应慢
解决方案 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 location / { proxy_pass http://backend; proxy_connect_timeout 60s ; proxy_send_timeout 60s ; proxy_read_timeout 60s ; proxy_buffering on ; proxy_buffer_size 4k ; proxy_buffers 8 4k ; proxy_busy_buffers_size 8k ; } upstream backend { server 127.0.0.1:8080 max_fails=3 fail_timeout=30s ; server 127.0.0.1:8081 backup; } proxy_next_upstream error timeout invalid_header http_500 http_502 http_503;proxy_next_upstream_tries 3 ;proxy_next_upstream_timeout 10s ;
排查方法 1 2 3 4 5 6 7 8 9 10 11 12 13 14 systemctl status tomcat systemctl status php-fpm ps aux | grep node netstat -tlnp | grep 8080 ss -tlnp | grep 8080 curl -v http://127.0.0.1:8080 tail -f /var/log/nginx/error.log | grep 502
503 Service Unavailable 含义 :服务暂时不可用。
常见原因
服务器过载
维护模式
后端服务不可用
解决方案 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 location / { return 503 ; add_header Retry-After 3600 ; } error_page 503 /maintenance.html;location = /maintenance.html { root /var/www/html; internal; } http { limit_conn_zone $binary_remote_addr zone=conn_limit:10m ; limit_req_zone $binary_remote_addr zone=req_limit:10m rate=10r/s; server { limit_conn conn_limit 10 ; limit_req zone=req_limit burst=20 nodelay; } } upstream backend { server 127.0.0.1:8080 ; server 127.0.0.1:8081 ; }
504 Gateway Timeout 含义 :网关超时。
常见原因
后端服务响应时间过长
proxy_read_timeout 设置过短
后端服务处理慢或卡死
解决方案 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 location / { proxy_pass http://backend; proxy_connect_timeout 60s ; proxy_send_timeout 300s ; proxy_read_timeout 300s ; send_timeout 300s ; } location /long-task { proxy_pass http://backend; proxy_read_timeout 300s ; proxy_intercept_errors on ; error_page 504 = @async ; } location @async { return 202 ; }
排查方法 1 2 3 4 5 6 7 8 9 10 time curl http://127.0.0.1:8080/api/slowtail -f /var/log/nginx/slow.logtop htop iostat
其他常见错误码 301/302 重定向 301 Moved Permanently(永久重定向) 1 2 3 4 5 6 7 8 9 10 11 12 server { listen 80 ; server_name example.com; return 301 https://$server_name $request_uri ; } server { server_name www.example.com; return 301 https://example.com$request_uri ; }
302 Found(临时重定向) 1 2 3 location /old { return 302 /new; }
304 Not Modified 含义 :资源未修改,使用缓存。
1 2 3 4 5 6 7 8 location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ { expires 30d ; add_header Cache-Control "public, immutable" ; etag on ; }
错误码分类总结 graph TB
A[Nginx错误码] --> B[4xx 客户端错误]
A --> C[5xx 服务器错误]
B --> B1[400 Bad Request 请求语法错误]
B --> B2[403 Forbidden 权限不足]
B --> B3[404 Not Found 资源不存在]
B --> B4[413 Request Too Large 请求体过大]
B --> B5[429 Too Many Requests 请求过于频繁]
B --> B6[499 Client Closed 客户端关闭连接]
C --> C1[500 Internal Server Error 服务器内部错误]
C --> C2[502 Bad Gateway 后端服务不可用]
C --> C3[503 Service Unavailable 服务暂时不可用]
C --> C4[504 Gateway Timeout 网关超时]
style B fill:#FF6B6B
style C fill:#FF8787
style B1 fill:#FFE5E5
style B2 fill:#FFE5E5
style B3 fill:#FFE5E5
style B4 fill:#FFE5E5
style B5 fill:#FFE5E5
style B6 fill:#FFE5E5
style C1 fill:#FFE5E5
style C2 fill:#FFE5E5
style C3 fill:#FFE5E5
style C4 fill:#FFE5E5
故障排查流程 通用排查步骤 flowchart TD
A[收到错误码] --> B{错误类型}
B -->|4xx| C[检查客户端请求]
B -->|5xx| D[检查服务器状态]
C --> C1[查看访问日志]
C1 --> C2[检查请求格式]
C2 --> C3[检查权限配置]
D --> D1[查看错误日志]
D1 --> D2[检查后端服务]
D2 --> D3[检查系统资源]
D3 --> D4[检查网络连接]
C3 --> E[解决问题]
D4 --> E
E --> F[验证修复]
style A fill:#74C0FC
style E fill:#51CF66
style F fill:#51CF66
日志分析 访问日志格式 1 2 3 4 5 log_format main '$remote_addr - $remote_user [$time_local ] "$request " ' '$status $body_bytes_sent "$http_referer " ' '"$http_user_agent " "$http_x_forwarded_for "' ; access_log /var/log/nginx/access.log main;
常用日志分析命令 1 2 3 4 5 6 7 8 9 10 11 12 13 14 awk '{print $9}' /var/log/nginx/access.log | sort | uniq -c | sort -rn grep " 502 " /var/log/nginx/access.log | tail -20 grep "192.168.1.100" /var/log/nginx/access.log tail -f /var/log/nginx/error.log | grep -E "error|warn" awk '{print $1}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -10
最佳实践 1. 错误页面配置 1 2 3 4 5 6 7 8 9 10 11 12 13 error_page 404 /404 .html;error_page 500 502 503 504 /50x.html;location = /404 .html { root /var/www/html; internal; } location = /50x.html { root /var/www/html; internal; }
2. 日志管理 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 error_log /var/log/nginx/error .log warn ;error_log /var/log/nginx/debug .log debug ;/var/log/nginx/*.log { daily missingok rotate 52 compress delaycompress notifempty create 0640 www-data adm sharedscripts postrotate [ -f /var/run/nginx.pid ] && kill -USR1 `cat /var/run/nginx.pid` endscript }
3. 监控和告警 1 2 3 4 5 6 7 8 9 10 11 12 13 14 location /nginx_status { stub_status on ; access_log off ; allow 127.0.0.1 ; deny all; } location /health { access_log off ; return 200 "healthy\n" ; add_header Content-Type text/plain; }
4. 性能优化 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 http { keepalive_timeout 65 ; keepalive_requests 100 ; client_body_buffer_size 128k ; client_header_buffer_size 1k ; large_client_header_buffers 4 4k ; client_body_timeout 12 ; client_header_timeout 12 ; send_timeout 10 ; gzip on ; gzip_vary on ; gzip_min_length 1000 ; gzip_types text/plain text/css application/json application/javascript; }
常见问题 FAQ Q1: 如何快速定位 502 错误? A:
检查后端服务是否运行:systemctl status <service>
检查端口是否监听:netstat -tlnp | grep <port>
查看 Nginx 错误日志:tail -f /var/log/nginx/error.log
测试后端连接:curl http://127.0.0.1:<port>
Q2: 403 错误但文件权限正常? A:
检查 SELinux 状态:getenforce
检查目录索引:确认 autoindex 配置
检查 Nginx 用户权限:ps aux | grep nginx
检查父目录权限:确保所有父目录都有执行权限
Q3: 如何自定义错误页面? A:
1 2 3 4 5 error_page 404 /custom_404.html;location = /custom_404.html { root /var/www/html; internal; }
Q4: 如何限制请求体大小? A:
1 2 3 4 5 6 7 8 http { client_max_body_size 10m ; location /upload { client_max_body_size 100m ; } }
Q5: 如何实现优雅降级? A:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 upstream backend { server 127.0.0.1:8080 ; server 127.0.0.1:8081 backup; } location / { proxy_pass http://backend; proxy_next_upstream error timeout http_500 http_502 http_503; error_page 502 503 504 = @fallback ; } location @fallback { root /var/www/html; try_files /maintenance.html =503 ; }
总结 理解 Nginx HTTP 错误码对于运维和故障排查至关重要:
关键要点
4xx 错误 :通常是客户端问题,检查请求格式、权限、资源是否存在
5xx 错误 :通常是服务器问题,检查后端服务、系统资源、网络连接
日志分析 :充分利用访问日志和错误日志定位问题
配置优化 :合理设置超时、缓冲区、限流等参数
监控告警 :建立完善的监控和告警机制
排查思路
先看日志 :错误日志和访问日志是首要信息来源
检查服务 :确认相关服务是否正常运行
验证配置 :使用 nginx -t 检查配置语法
测试连接 :使用 curl 等工具测试连接
系统资源 :检查 CPU、内存、磁盘、网络等资源
通过系统化的排查方法和合理的配置,可以有效减少和快速解决 Nginx 错误码问题,提高系统的稳定性和可用性。