Nginx短连接
先看一下Nginx短连接的情况。
Nginx上抓包短连接
Tcpdump显示效果
[root@nginx-plus-2 ~]# tcpdump -i ens192 host 192.168.1.225 and tcp -A -s 0 -n
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on ens192, link-type EN10MB (Ethernet), capture size 262144 bytes
#TCP三次握手
13:06:10.674757 IP 192.168.1.135.45750 > 192.168.1.225.webcache: Flags [S], seq 1889946011, win 29200, options [mss 1460,sackOK,TS val 2776265370 ecr 0,nop,wscale 7], length 0
E..<;.@.@.{.............p.I.......r............
.zr.........
13:06:10.675391 IP 192.168.1.225.webcache > 192.168.1.135.45750: Flags [S.], seq 1966123495, ack 1889946012, win 28960, options [mss 1460,sackOK,TS val 999954489 ecr 2776265370,nop,wscale 7], length 0
E..<..@.@...............u0..p.I...q :..........
;..9.zr.....
13:06:10.675431 IP 192.168.1.135.45750 > 192.168.1.225.webcache: Flags [.], ack 1, win 229, options [nop,nop,TS val 2776265371 ecr 999954489], length 0
E..4;.@.@.{ ............p.I.u0.............
.zr.;..9
#Nginx向Tomcat发起GET请求
13:06:10.675511 IP 192.168.1.135.45750 > 192.168.1.225.webcache: Flags [P.], seq 1:158, ack 1, win 229, options [nop,nop,TS val 2776265371 ecr 999954489], length 157: HTTP: GET / HTTP/1.0
E...;.@.@.zk............p.I.u0.......|.....
.zr.;..9GET / HTTP/1.0
X-Forwarded-For: 192.168.1.35
X-Real-IP: 192.168.1.35
Host: 192.168.1.225:8080
Connection: close #短连接
User-Agent: curl/7.64.1
Accept: */*
#上游TOMCAT服务器返回的内容
13:06:10.675759 IP 192.168.1.225.webcache > 192.168.1.135.45750: Flags [.], ack 158, win 235, options [nop,nop,TS val 999954490 ecr 2776265371], length 0
E..4..@.@..9............u0..p.J9...........
;..:.zr.
13:06:10.682146 IP 192.168.1.225.webcache > 192.168.1.135.45750: Flags [P.], seq 1:262, ack 158, win 235, options [nop,nop,TS val 999954496 ecr 2776265371], length 261: HTTP: HTTP/1.1 200 OK
E..9..@.@..3............u0..p.J9.....h.....
;..@.zr.HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Set-Cookie: JSESSIONID=A81D89FB21B81086B2ADE210BE79C825; Path=/; HttpOnly
Content-Type: text/html;charset=ISO-8859-1
Content-Length: 20
Date: Mon, 07 Sep 2020 05:10:21 GMT
Connection: close
Welcome to Tomcat1
#Nginx回应tomcat的返回内容的ack
13:06:10.682182 IP 192.168.1.135.45750 > 192.168.1.225.webcache: Flags [.], ack 262, win 237, options [nop,nop,TS val 2776265378 ecr 999954496], length 0
E..4;.@.@.{.............p.J9u0.............
.zr.;..@
#四次挥手,Nginx主动断开连接
13:06:10.682352 IP 192.168.1.135.45750 > 192.168.1.225.webcache: Flags [F.], seq 158, ack 262, win 237, options [nop,nop,TS val 2776265378 ecr 999954496], length 0
E..4;.@.@.{.............p.J9u0.............
.zr.;..@
#上游tomcat将FIN和ACK合成一次返回了
13:06:10.682429 IP 192.168.1.225.webcache > 192.168.1.135.45750: Flags [F.], seq 262, ack 158, win 235, options [nop,nop,TS val 999954497 ecr 2776265378], length 0
E..4..@.@..7............u0..p.J9...........
;..A.zr.
13:06:10.682449 IP 192.168.1.135.45750 > 192.168.1.225.webcache: Flags [.], ack 263, win 237, options [nop,nop,TS val 2776265378 ecr 999954497], length 0
E..4;.@.@.{.............p.J:u0.............
.zr.;..A
#暂时不知道为什么会多了这一段,如果是客户端直接访问Tomcat是没有这一段的
13:06:10.682522 IP 192.168.1.225.webcache > 192.168.1.135.45750: Flags [.], ack 159, win 235, options [nop,nop,TS val 999954497 ecr 2776265378], length 0
E..4..@.@..6............u0..p.J:...........
;..A.zr.
Wireshark显示效果
-
出现大量TIME_WAIT的情况
- 导致 nginx端出现大量TIME_WAIT的情况有两种:
- keepalive_requests设置比较小,高并发下超过此值后nginx会强制关闭和客户端保持的keepalive长连接;(nginx主动关闭连接后导致nginx出现TIME_WAIT)
- keepalive设置的比较小(空闲数太小),导致高并发下nginx会频繁出现连接数震荡(超过该值会关闭连接),不停的关闭、开启和后端server保持的keepalive长连接;
- 导致后端server端出现大量TIME_WAIT的情况:(nginx主动关闭连接) nginx没有打开和后端的长连接,即:没有设置proxy_http_version 1.1;和proxy_set_header Connection "";从而导致后端server每次关闭连接,高并发下就会出现server端出现大量TIME_WAIT。
- 导致 nginx端出现大量TIME_WAIT的情况有两种:
长连接
Nginx配置长连接
1,2,3是必须配置的
events {}
http {
log_format haha '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for" $server_name $upstream_addr $upstream_status $request_time $upstream_response_time';
upstream cr7back {
#1.连接池里面最大的空闲连接数量,
#keepalive 这个参数一定要小心设置,尤其对于QPS比较高的场景,
#推荐先做一下估算,根据QPS和平均响应时间大体能计算出需要的长连接的数量。
#比如前面10000 QPS和100毫秒响应时间就可以推算出需要的长连接数量大概是1000。
#然后将keepalive设置为这个长连接数量的10%到30%。
keepalive 10;
keepalive_requests 1000; #设置一个keep-alive连接上可以服务的请求的最大数量。当最大请求数量达到时,连接被关闭。默认是100。
server 192.168.1.225:8080;
}
server {
#Nginx 默认支持 HTTP协议的 keep-alive持续连接(长连接)功能,
#其默认的超时时间为75秒,在此期间内后续的http请求可以复用已建立的TCP连接,
#从而节省新建TCP连接握手的时间与资源。
keepalive_timeout 60 60;
access_log /var/log /nginx/haha.log haha;
listen 80;
location / {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Connection "keep-alive"; #2.设置Connection为长连接,默认为close,这里""里的内容只要不是close,都会是长连接
proxy_http_version 1.1; #3.http1.1版本才支持长连接,默认的是1.0版本不支持长连接
proxy_pass http: //cr7back;
}
}
keepalive_timeout 指令
语法: keepalive_timeout timeout [header_timeout]
默认值: keepalive_timeout 75s;
使用字段: http, server, location
参数:
参数1指定了客户端与服务器 keep-alive的超时时间,值为0将禁用 keep-alive功能。
参数2(可选)在HTTP响应头"Keep-Alive: timeout=time" 字段中设置一个值。
注意客户端curl -I的结果中Connection: keep-alive并不代表是长连接。
Nginx抓包长连接
Tcpdump显示效果
[root@nginx-plus-2 ~]# tcpdump -i ens192 host 192.168.1.225 and tcp -A -s 0 -n
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on ens192, link-type EN10MB (Ethernet), capture size 262144 bytes
#TCP三次握手
14:53:10.519365 IP 192.168.1.135.52224 > 192.168.1.225.webcache: Flags [S], seq 3447497727, win 29200, options [mss 1460,sackOK,TS val 2782685215 ecr 0,nop,wscale 7], length 0
E..<..@.@..".............|........r............
..h.........
14:53:10.520031 IP 192.168.1.225.webcache > 192.168.1.135.52224: Flags [S.], seq 1296273318, ack 3447497728, win 28960, options [mss 1460,sackOK,TS val 1006374594 ecr 2782685215,nop,wscale 7], length 0
E..<..@.@...............MC...|....q .d.........
;.....h.....
14:53:10.520069 IP 192.168.1.135.52224 > 192.168.1.225.webcache: Flags [.], ack 1, win 229, options [nop,nop,TS val 2782685216 ecr 1006374594], length 0
E..4..@.@..).............|..MC.............
..h ;...
#Nginx向Tomcat发起GET请求
14:53:10.520133 IP 192.168.1.135.52224 > 192.168.1.225.webcache: Flags [P.], seq 1:152, ack 1, win 229, options [nop,nop,TS val 2782685216 ecr 1006374594], length 151: HTTP: GET / HTTP/1.1
E.....@.@................|..MC.......v.....
..h ;...GET / HTTP/1.1
X-Forwarded-For: 192.168.1.35
X-Real-IP: 192.168.1.35
Connection: keep-alive #长连接
Host: cr7back
User-Agent: curl/7.64.1
Accept: */*
#上游TOMCAT服务器返回的内容
14:53:10.520450 IP 192.168.1.225.webcache > 192.168.1.135.52224: Flags [.], ack 152, win 235, options [nop,nop,TS val 1006374594 ecr 2782685216], length 0
E..4.e@.@.4.............MC...|......]......
;.....h
14:53:10.522514 IP 192.168.1.225.webcache > 192.168.1.135.52224: Flags [P.], seq 1:243, ack 152, win 235, options [nop,nop,TS val 1006374596 ecr 2782685216], length 242: HTTP: HTTP/1.1 200 OK
E..&.f@.@.3.............MC...|.............
;.....h HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Set-Cookie: JSESSIONID=F1102B1DF0A84DF7C477224D43BF2467; Path=/; HttpOnly
Content-Type: text/html;charset=ISO-8859-1
Content-Length: 20
Date: Mon, 07 Sep 2020 06:57:21 GMT
Welcome to Tomcat1
#Nginx回应tomcat的返回内容的ack
14:53:10.522535 IP 192.168.1.135.52224 > 192.168.1.225.webcache: Flags [.], ack 243, win 237, options [nop,nop,TS val 2782685218 ecr 1006374596], length 0
E..4..@.@..'.............|..MC.............
..h";...
#可以看到Nginx并没有主动断开连接
Wireshark显示效果
TCP keepalive和HTTP keepalive
http keep-alive与tcp keep-alive,不是同一回事,意图不一样。http keep-alive是为了让tcp活得更久一点,以便在同一个连接上传送多个http,提高socket的效率。而tcp keep-alive是TCP的一种检测TCP连接状况的保鲜机制。tcp keep-alive保鲜定时器,支持三个系统内核配置参数:
tcp_keepalive_time #keepalive的闲置时长,默认为7200s
tcp_keepalive_intvl #keepalive探测包的发送间隔,默认为75s
tcp_keepalive_probes #探测包的发送次数,默认为9次
临时修改:
echo 1800 > /proc/sys/net/ipv4/tcp_keepalive_time
echo 15 > /proc/sys/net/ipv4/tcp_keepalive_intvl
echo 5 > /proc/sys/net/ipv4/tcp_keepalive_probes
永久修改: 编辑/etc/sysctl.conf
net.ipv4.tcp_keepalive_time=1800
net.ipv4.tcp_keepalive_intvl=15
net.ipv4.tcp_keepalive_probes=9
修改完后,sysctl -p 使其生效。
当网络两端建立了TCP连接之后,闲置idle(双方没有任何数据流发送往来)了 tcp_keepalive_time秒后,服务器内核就会尝试向客户端发 送侦测包,来判断TCP连接状况(有可能客户端崩溃、强制关闭了应用、主机不可达等等)。如果没有收到对方的回答(ack包),则会在 tcp_keepalive_intvl秒后再次尝试发送侦测包,直到收到对对方的ack,如果一直没有收到对方的ack,一共会尝试 tcp_keepalive_probes次,每次的间隔时间在这里分别是15s, 30s, 45s, 60s, 75s。如果尝试tcp_keepalive_probes次,依然没有收到对方的ack包,则会丢弃该TCP连接。TCP连接默认闲置时间是2小时,一般 设置为30分钟足够了。也就是说,仅当nginx的keepalive_timeout值设置高于tcp_keepalive_time,并且距此tcp连接传输的最后一 个http响应,经过了tcp_keepalive_time时间之后,操作系统才会发送侦测包来决定是否要丢弃这个TCP连接。一般不会出现这种情况, 除非你需要这样做。