date: 2020-07-16title: nginx代理超时 #标题
tags: nginx代理超时 #标签
categories: nginx # 分类
问题描述
最近一个新项目,遇到个问题,是这样的: 客户那边提供两台机器,部署python程序、nginx做静态资源服务器,后端数据库,然后如果要访问客户那边,需要申请网络策略,放行相关IP的流量,因此,从我们公司机房的nginx上,配置了server主机,代理到客户那边,然后域名解析的是我们这边的IP。好吧,可能说的有些不太清楚,下面来总结下一个请求的流程:
客户请求 ===》F5硬负载 ===》三台nginx代理 ===》 客户那边的nginx静态资源服务器。
也就是说,每次客户请求,都是我们这边的三台nginx代理,去访问客户那边的nignx静态资源服务器。但是呢,在访问页面时,总会出现 504 状态码,网关超时。
问题排查
首先,给我们的三台nginx代理,单独写了个日志文件,配置如下:
location / {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_connect_timeout 600;
proxy_send_timeout 600;
proxy_read_timeout 600;
proxy_pass http://backend;
error_log /tmp/sjy_error.log;
access_log /tmp/sjy_access.log main;
# access_log格式增加变量($request_time $upstream_response_time)如下:
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"'
'$ssl_protocol $ssl_cipher $upstream_addr $request_time $upstream_response_time
# 关于这两个变量解释如下:
$request_time: 表示从接受用户请求的第一个字节到发送完整响应数据的时间,即包括接收请求数据时间、程序响应时间、输出响应数据时间。
$upstream_response_time: 表示从nginx向后端(upstream定义的主机列表)建立连接开始到接受完数据,然后关闭连接为止的时间。
然后看日志,发现这三台nginx代理去访问客户那边的静态资源时,总是有两台机器的请求时间特别长,某些页面的状态还是pending(但在nginx代理上直接请求这个页面,则响应很快,故怀疑问题出在这三台nginx代理上)。经过一番挠头,也没找到问题所在,最后无奈,怀疑是我们机房网络问题,找组长来帮忙看看….过程就不详述了,最后找到的问题的原因就在于,客户那边的nginx静态资源服务器,内核参数是这样配置的:
net.core.somaxconn = 4000
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_tw_recycle = 1
net.ipv4.tcp_fin_timeout = 30
net.ipv4.tcp_keepalive_time = 1200
net.ipv4.tcp_max_syn_backlog = 8192
net.ipv4.tcp_max_tw_buckets = 5000
问题就在net.ipv4.tcp_tw_recycle = 1
这个参数上,百度一下,看到如下:
好吧,我们这三个nginx代理,共用一个出口IP去访问客户那边的nginx,就是上图中说的场景,将net.ipv4.tcp_tw_recycle = 1
参数删除(默认值为0,关闭),sysctl -p 刷新,nginx -s reload 重启客户那边的nignx,再次访问测试,问题解决。耶,最后夸夸我们的组长,不愧是身经百战,优秀 !!!
总结教训
通过此次故障,警示我们在进行日常运维,新项目部署,修改,重启等的操作上,需要我们严格按照流程仔细去进行测试,评估修改后的风险及出现问题回退和解决方法;特别是对内核参数的修改一定要理解透彻,不能盲目修改(这个内核参数不是我加的,我加内核参数的话,一定是先看个大概意思,再操作【手动甩锅】),尽量让故障率降低。