目录

Nginx 支持 keep-alive 长连接

KeepAlive 是长连接的意思。客户端发起 HTTP 请求前需要先与服务端建立 TCP 连接,每次TCP连接都需要三次握手来确定,三次交互不仅会增加消费时间,还会增加网络流量。HTTP 请求是请求应答式,如果能知道每个请求头与响应体的长度,就可以在一个连接上执行多个请求,这个就是所谓的长连接。

概念

Persistent HTTP connections have a number of advantages

HTTP 协议采用请求-应答模式,当使用普通模式,即非 KeepAlive 模式时,每个请求/应答客户和服务器都要新建一个连接,完成之后立即断开连接(HTTP 协议为无连接的协议);当使用 Keep-Alive 模式(又称持久连接/连接重用)时,Keep-Alive 功能使客户端到服务器端的连接持续有效,当出现对服务器的后继请求时,Keep-Alive 功能避免了建立或者重新建立连接。

http://om804c7s2.bkt.clouddn.com/2018-01-06-15152071602677.jpg

支持 keep alive

当使用 nginx 作为反向代理时,为了支持长连接,需要做到两点

  • clientnginx 的连接是长连接
  • nginxserver 的连接是长连接

保持和 client 的长连接

  • client 发送的 HTTP 请求要求 keep alive
  • nginx 设置上支持 keep alive

HTTP 配置

keepalive_timeout

默认 75s,一般情况下也够用,对于一些请求比较大的内部服务器通讯的场景,适当加大为 120s 或者 300s。第二个参数通常可以不用设置

第一个参数设置 keep-alive 客户端连接在服务器端保持开启的超时值。值为 0 会禁用 keep-alive 客户端连接。可选的第二个参数在响应的 header 域中设置一个值 Keep-Alive: timeout=time。这两个参数可以不一样

keepalive_requests

默认 100,对于 QPS 较高的场景,非常有必要加大这个参数,以避免出现大量连接被生成再抛弃的情况,减少 TIME_WAIT。这个参数的真实含义是指一个 keep alive 建立之后,nginx 就会为这个连接设置一个计数器,记录这个 keep alive 的长连接上已经接收并处理的客户端请求的数量。如果达到这个参数设置的最大值时,则 nginx 会强行关闭这个长连接,逼迫客户端不得不重新建立新的长连接

用于设置一个 keep-alive 连接上可以服务的请求的最大数量。当最大请求数量达到时,连接被关闭

保持和 server 的长连接

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
http {
    keepalive_timeout 100s;
    keepalive_requests 1000;

    upstream dev.proxy.com {
        server 192.168.10.11:8081 weight=1 max_fails=2 fail_timeout=30s;
        server 192.168.10.10:8081 weight=1 max_fails=2 fail_timeout=30s;
        keepalive 300;
    }

    server {
        listen 80 default_server;
        listen [::]:80 ipv6only=on;
        server_name dev.proxy.com;
        charset utf-8;

        location / {
            index index.php index.html index.htm;
            proxy_pass http://dev.proxy.com/;
            proxy_set_header Host $Host;
            proxy_set_header x-forwarded-for $remote_addr;
            proxy_set_header X-Real-IP $remote_addr;
            add_header Cache-Control no-store;
            add_header Pragma no-cache;
            proxy_http_version 1.1;
            proxy_set_header Connection "";

            client_max_body_size 3072k;
            client_body_buffer_size 128k;
        }
    }
}

合理的设置 keep-alive 值可以非常有效的缓冲请求和应答不均匀,缓解连接数量的反复震荡

连接数量震荡的两个表现

  • 连接不够用,造成新建连接
  • 连接空闲,造成关闭连接

统计在一台前端机上高峰时间 TCP 连接的情况

1
$ netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a,S[a]}'

导致 nginx 端出现大量 TIME_WAIT 的两种情况

  • keepalive_requests 设置比较小,高并发下超过此值后 nginx 会强制关闭和客户端保持的keepalive 长连接(主动关闭连接后导致 nginx 出现 TIME_WAIT)
  • keepalive 设置的比较小(空闲数太小),导致高并发下 nginx 会频繁出现连接数震荡(超过该值会关闭连接),不停的关闭开启和后端 server 保持的 keep-alive 长连接

导致后端 server 端出现大量 TIME_WAIT 的情况

  • nginx 没有打开和后端的长连接,即:没有设置 proxy_http_version 1.1;proxy_set_header Connection ""; 从而导致后端 server 每次关闭连接,高并发下就会出现 server 端出现大量 TIME_WAIT