当nginx反向代理遇到502错误
- 最近我司某业务(
nginx 1.22.0
反向代理后端Java服务,不涉及php)在运行一段时间后不定期出现502 Bad Gateway,nginx日志报错如下:
2023/10/16 15:10:26 [error] 54381#0: *15225751 recv() failed (104: Connection reset by peer) while reading response header from upstream, client: x.x.x.x, server: _, request: "GET /manager HTTP/1.0, upstream: "http://x.x.x.x:300081/manager", host: "x.x.x.x"
- 该业务在公网与内网环境的访问逻辑如下,其中内网用户访问一直ok,而公网则不定期出现502错误,所以排除路由器及k8s容器,初步判定问题出在公网nginx服务器上
方式1:公网用户 --> nginx(公网域名:port) --> 路由器映射端口(内网ip:port) --> k8s(nginx代理java服务)
方式2:内网用户 --> 路由器映射端口(内网ip:port) --> k8s(nginx代理java服务)
分析过程
- 由于nginx这一类的代理出现Connection reset的场景复杂,原因多样,最常见的原因是上传文件过大,传输时间过长,然后连接被中断
- 本案例中公网nginx使用的是HTTP 1.0,而后端k8s容器中nginx使用的是HTTP 1.1(注:HTTP 1.1协议默认开启keepalive功能),所以猜测可能是前端nginx与后端java服务或后端nginx的keepalive timeout时间不一致导致此问题的发生
注:执行
curl -I http://ip地址
可以参看HTTP协议版本
处理步骤
- 第1步,调整
nginx.conf
如下参数,启用 http 1.1 协议以支持长连接,并根据实际情况调整timeout参数
worker_processes auto; #.核心参数
worker_rlimit_nofile 65535;
#.其他省略...
events {
use epoll;
worker_connections 30000; #.核心参数,请根据实际情况调整
multi_accept on;
}
http {
#.其他省略...
keepalive_timeout 120; #.核心参数,请根据实际情况调整
keepalive_requests 1000; #.核心参数,请根据实际情况调整
client_header_timeout 10; #.核心参数,请根据实际情况调整
client_body_timeout 10; #.核心参数,请根据实际情况调整
send_timeout 600; #.核心参数,请根据实际情况调整
server {
listen 80;
location / {
#.其他省略...
proxy_pass http://xxx:30081;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header REMOTE-HOST $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Connection keep-alive; #.核心参数,指定Connection为keep-alive
proxy_http_version 1.1; #.核心参数,启用http1.1协议
proxy_connect_timeout 300s; #.核心参数,请根据实际情况调整
proxy_send_timeout 300s; #.核心参数,请根据实际情况调整
proxy_read_timeout 300s; #.核心参数,请根据实际情况调整
client_max_body_size 50m; #.核心参数,请根据实际情况调整
}
}
}
- 第2步,先执行
nginx -t
确认参数无误,再执行nginx -s reload
热重启nginx服务 - 第3步,设置 ulimit 系统最大打开的文件数量
ulimit -SHn 65535
cat /etc/rc.local | grep ulimit || echo "ulimit -HSn 65535" >> /etc/rc.local
- 第4步,优化linux内核,修改
/etc/sysctl.conf
配置如下参数,然后/sbin/sysctl -p /etc/sysctl.conf
使配置立即生效
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_tw_reuse = 1 #.核心参数
net.ipv4.tcp_tw_recycle = 1 #.核心参数
net.ipv4.tcp_timestamps = 1 #.核心参数
net.ipv4.tcp_keepalive_time = 300 #.核心参数,请根据实际情况调整
net.ipv4.tcp_max_tw_buckets = 10000 #.核心参数,请根据实际情况调整
net.ipv4.ip_local_port_range = 1024 65535
net.core.somaxconn = 8192 #.核心参数,请根据实际情况调整
以上,第1、2步必做,第3、4步选做。