随着 web 服务器的负载逐渐升高,我们就会开始遭遇 NginX 的某些奇怪限制。连接被丢弃,内核不停报 SYN flood。而这时,平均负荷和 CPU 使用率都很小,服务器明明是可以处理更多连接的状态,真令人沮丧。
经过调查,发现有非常多处于 TIME_WAIT 状态的连接。这是其中一个服务器的输出:
- ss -s
- Total: 388 (kernel 541)
- TCP: 47461 (estab 311, closed 47135, orphaned 4, synrecv 0, timewait 47135/0), ports 33938
Transport Total IP IPv6 * 541 - - RAW 0 0 0 UDP 13 10 3 TCP 326 325 1 INET 339 335 4 FRAG 0 0 0
有 47135 个 TIME_WAIT 连接!而且,从 ss 可以看出,它们都是已经关闭的连接。这说明,服务器已经消耗了绝大部分可用端口,同时也暗示我们,服务器是为每个连接都分配了新端口。调优网络对这个问题有一点帮助,但是端口仍然不够用。
经过继续研究,我找到了一个关于上行连接 keepalive 指令的文档,它写道:
有趣。理论上,这个设置是通过在缓存的连接上传递请求来尽可能减少连接的浪费。文档中还提到,我们应该把 proxy_http_version 设为 "1.1",并清除 "Connection" 头部。经过进一步的研究,我发现这是一种很好的想法,因为 HTTP/1.1 相比 HTTP1.0,大大优化了 TCP 连接的使用率,而 Nginx 默认用的是 HTTP/1.0。
按文档的建议修改后,我们的上行配置文件变成这样:
- upstream backend_nodejs {
- server nodejs-3:5016 max_fails=0 fail_timeout=10s;
- server nodejs-4:5016 max_fails=0 fail_timeout=10s;
- server nodejs-5:5016 max_fails=0 fail_timeout=10s;
- server nodejs-6:5016 max_fails=0 fail_timeout=10s;
- keepalive 512;
- }
我还按它的建议修改了 server 一节的 proxy 设置。同时,加了一个 p roxy_next_upstream 来跳过故障的服务器,调整了客户端的 keepalive_timeout,并关闭访问日志。配置变成这样:
- server {
- listen 80;
- server_name fast.gosquared.com;
client_max_body_size 16M; keepalive_timeout 10;
location / { proxy_next_upstream error timeout http_500 http_502 http_503 http_504; proxy_set_header Connection ""; proxy_http_version 1.1; proxy_pass http://backend_nodejs; }
access_log off; error_log /dev/null crit; }
采用新的配置后,我发现服务器们占用的 socket 降低了 90%。现在可以用少得多的连接来传输请求了。新的输出如下:
- ss -s
Total: 558 (kernel 604) TCP: 4675 (estab 485, closed 4183, orphaned 0, synrecv 0, timewait 4183/0), ports 2768
Transport Total IP IPv6 * 604 - - RAW 0 0 0 UDP 13 10 3 TCP 492 491 1 INET 505 501 4
来源: http://www.phperz.com/article/17/0427/270618.html