Nginx 支持 keep-alive 长连接
概念
Persistent HTTP connections have a number of advantages
HTTP 协议采用请求-应答模式,当使用普通模式,即非 KeepAlive 模式时,每个请求/应答客户和服务器都要新建一个连接,完成之后立即断开连接(HTTP 协议为无连接的协议);当使用 Keep-Alive 模式(又称持久连接/连接重用)时,Keep-Alive 功能使客户端到服务器端的连接持续有效,当出现对服务器的后继请求时,Keep-Alive 功能避免了建立或者重新建立连接。
支持 keep alive
当使用 nginx 作为反向代理时,为了支持长连接,需要做到两点
从
client到nginx的连接是长连接从
nginx到server的连接是长连接
保持和 client 的长连接
client发送的HTTP请求要求keep alivenginx设置上支持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 的长连接
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 连接的情况
$ 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
