nginx $upstream_addr
keeps the IP address and port, or the path to the UNIX-domain socket of the upstream server. If several servers were contacted during request processing, their addresses are separated by commas, e.g. “192.168.1.1:80, 192.168.1.2:80, unix:/tmp/sock”. If an internal redirect from one server group to another happens, initiated by “X-Accel-Redirect” or error_page, then the server addresses from different groups are separated by colons, e.g. “192.168.1.1:80, 192.168.1.2:80, unix:/tmp/sock : 192.168.10.1:80, 192.168.10.2:80”. If a server cannot be selected, the variable keeps the name of the server group.
$ cat /etc/nginx/conf.d/test.com.conf
upstream backend-servers{
server 127.0.0.1:9527;
server 127.0.0.1:9528;
server 127.0.0.1:9529;
}
server {
listen 80;
server_name www.test.com;
access_log /va/log/test.com.log access;
location / {
proxy_pass http://backend-servers;
}
}
当有一个可用的服务的时候,upstream_addr记录的是这个可用后端的ip:port;
非动态注册(测试用例就是写死的upstream),nginx会去重试连接那些失效server,此时upstream_addr显示多个值,尝试链接了多少个,就逗号分割记录多少个;
当关停所有后端实例后,upstream_addr显示为“backend-servers”,即upstream定义的名字,出现这个,表明没有一个可用的后端服务
10.19.42.241######-######-######[20/Feb/2023:11:09:16 +0800]######"GET /version-control/xxx HTTP/1.1"######404######568######"-"######"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.128 Safari/537.36; Qing/0.0.7; App/test 10086/4.1.0; 4.1.0 (2212151455); deviceId:b68aad8776277d5e930239ceac59a2d6; clientId:10086;lang:zh-CN;bno:4.1.0(2212151455);"######0.000######www.test.com######b4340dccb2e797b626a6139e4862a546######upstest01######502######-######http######0.000######-######901
10.19.42.234######-######-######[20/Feb/2023:09:57:17 +0800]######"POST /gateway/xxx HTTP/1.1"######404######568######"-"######"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.128 Safari/537.36; Qing/0.0.7; App/test 10086/4.1.0; 4.1.0 (2212151455); deviceId:d283d1e27e540cfdd8e13e3f2d56a562; clientId:10086;lang:zh-CN;bno:4.1.0(2212151455);"######0.000######www.test.com######0ebb7d08ada07e02c89726bed3b04392######upstest02######502######-######http######0.000######-######1047
client <---> nginx <--- > upstream
分析nginx日志,发现 :
- $upstream_addr 字段出现的是 upstream后面定义的名字
- upstream 给 nginx返回的 http_code 为 502
- nginx 给 client 返回的 http_code 为 404
从nginx log 中$upstream_addr 字段输出upstream的名称 ,不对劲 应该响应的是 某个实例的 ip:port
为什么会直接返回 upstream的名称呢? 那是因为nginx检测后端发现没有存活可以用的 实例
明明后端实例都存活的啊,nginx为什么认为他们都不可用呢?
原因是在一个存活检测周期里,nginx向后端建立连接临时端口不够用了,大量处于 TIME-WAIT的 tcp连接占据了本地端口,来不及释放,那么在这个 存活检测周期里,你没有排到号。。。nginx 就认为 没有存活的 upstream 实例!
查看nginx服务器tcp连接状态:
ss -s
ss -tan | awk '{++S[$1]} END {for(a in S) print a, S[a]}'
netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'
image.png
解决方法:
- 增加nginx 服务器数量
- 调优nginx服务器内核参数,增加对临时端口的复用能力
# vim /etc/sysctl.conf
###########################
net.ipv4.tcp_tw_recycle = 0
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_timestamps = 1
############################
# sysctl -p
如果你后续想将上面的 内核参数改回来,改为:
net.ipv4.tcp_tw_recycle = 0
net.ipv4.tcp_tw_reuse = 0
net.ipv4.tcp_timestamps = 0
端口不复用 ,改为 复用 nginx可以不重启;正在复用,突然改为不复用。。。已存在的连接会怎样?
听哥一句,修改完sysctl -p 之后一定要 重启nginx进程,不只是 reload ,不然你会发现,所有已经建立的连接被全部reset了!!!
参考
nginx日志$upstream_addr多个值
https://mephisto.cc/tech/upstream_addr/
https://help.aliyun.com/document_detail/405072.html
nginx log输出upstream的名字
https://bbs.csdn.net/topics/393712408
网友评论