Nginx作前端Proxy时TIME_WAIT过多的问题

咱们的DSP系统目前基本非凌晨时段的QPS都在10W以上,咱们使用Golang来处理这些HTTP请求,Web服务器的前端用Nginx来作负载均衡,经过Nginx的proxy_pass来与Golang交互。因为nginx代理使用了短连接的方式和后端交互的缘由,使得系统TIME_WAIT的tcp链接不少:
shell> netstat -n | awk '/^tcp/ {++state[$NF]} END {for(key in state) print key,"\t",state[key]}'
TIME_WAIT 250263
CLOSE_WAIT 57
FIN_WAIT2 3
ESTABLISHED 2463
SYN_RECV 8

ss 比 netstat 要快,因此也能够用下面的命令来查看:html

shell> ss -ant | awk 'NR>1 {++s[$1]} END {for(k in s) print k,s[k]}'

这会占用系统过多的端口,还浪费了系统资源,因此咱们必须想办法减小TIME_WAIT。前端

TIME_WAIT致使占用过多端口的一个影响是会占用咱们须要使用到的端口,例如咱们有个服务监听的端口为8012,重启的时候常常会提示端口被占用。
经过查看/proc/sys/net/ipv4/ip_local_port_range能够知道设置的Linux内核自动分配端口的端口范围:linux

shell> cat /proc/sys/net/ipv4/ip_local_port_range
1025 65535

对于这个设置系统就会从1025~65535这个范围内随机分配端口来用于链接,而咱们服务的8012端口恰好在这个范围以内,因此若是8012恰好被系统分配出去使用了,则启动咱们服务的时候,就会提示端口被占用。nginx

因此咱们须要设置/proc/sys/net/ipv4/ip_local_reserved_ports来告诉系统给咱们预留哪些端口,不能够用于自动分配。shell

shell> vim /etc/sysctl.conf
net.ipv4.ip_local_reserved_ports = 8012,11211-11220

shell> sysctl -p

关于预留端口的更具体信息能够参考:vim

上面咱们解决了端口占用问题,可是咱们仍是须要解决TIME_WAIT过多的问题。
Nginx 1.1以上版本的upstream已经支持keep-alive的,因此咱们能够开启Nginx proxy的keep-alive来减小tcp链接:后端

upstream http_backend {
    server 127.0.0.1:8080;

    keepalive 16;
}

server {
    ...

    location /http/ {
        proxy_pass http://http_backend;
        proxy_http_version 1.1;
        proxy_set_header Connection "";
        ...
    }
}

能够参加Nginx的官方文档: http://nginx.org/cn/docs/http/ngx_http_upstream_module.html#keepalive服务器

开了keep-alive以后,TIME_WAIT明显减小:网络

shell> netstat -n | awk '/^tcp/ {++state[$NF]} END {for(key in state) print key,"\t",state[key]}'
TIME_WAIT 12612
CLOSE_WAIT 11
FIN_WAIT1 4
FIN_WAIT2 1
ESTABLISHED 7667
SYN_RECV 3

另外很多文章提到能够修改系统的/etc/sysctl.conf配置来减小TIME_WAIT的tcp链接:负载均衡

net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_tw_recycle = 1

参见: http://blog.s135.com/post/271/

不过开启tcp_tw_recycle可能会带来一些不稳定的网络问题,请参考:

关于sysctl相关配置的说明,请参考:
https://www.kernel.org/doc/Documentation/networking/ip-sysctl.txt

 

参考文章:

相关文章
相关标签/搜索