仔细看参数--NGINX之tcp_nodelay

仔细看参数--NGINX之tcp_nodelay

2023年7月23日发(作者:)

仔细看参数--NGINX之tcp_nodelay⼀、知识准备● 在nginx优化中有个经常需要设置的参数,tcp_nodelay● 该参数最核⼼的功能,就是把⼩包组成成⼤包,提⾼带宽利⽤率也就是著名的nagle算法● tcp协议中,有⼀个现象:应⽤层数据可能很低(⽐如1个字节),⽽传输层开销有40字节(20字节的IP头+20字节的TCP头)。这种情况下⼤部分都是控制包的传输,既加⼤了带宽的消耗,带宽利⽤率也不⾼● nagle算法就是为了解决这个问题。在发出去的数据还未被确认之前,或者说还没有收到对端的ack之前,新⽣成的⼩包是不允许被发送的,必须要凑满⼀个MSS或者等到收到确认后再发送,直⾄超时⼆、环境准备组件版本OSUbuntu 18.04.1 LTSdocker18.06.0-ce客户端 : 192.168.17.171服务端 : 192.168.17.173三、打开nagle算法192.168.17.173,先准备⼀个nginx配置⽂件,并且打开nagle算法,设置tcp_nodelay off;root@k8s-node2:/tmp# more er nginx;worker_processes 1;error_log /var/log/nginx/ warn;pid /var/run/;events { worker_connections 1024;}http { include /etc/nginx/; default_type application/octet-stream; log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; access_log /var/log/nginx/ main; sendfile on; tcp_nodelay off; keepalive_timeout 65; include /etc/nginx/conf.d/*.conf;}启动容器root@k8s-node2:/tmp# docker run -d --name nginx_delay -v /tmp/:/etc/nginx/ -p 80:80 nginx:latest6b7d5a5d3c3ed021fed6847d138837754c5732979d1c829ec62107ec80440db8root@k8s-node2:/tmp# docker ps | grep nginx_delay6b7d5a5d3c3e nginx:latest "nginx -g 'daemon of…" 7 seconds ago Up 6 seconds 0.0.0.0:80->80/tcp nginx_delay⾸先使⽤tcpdump抓取本机的80端⼝的流量:root@k8s-node2:/tmp# tcpdump -i ens3 port 80 -afexnnvv -w nginx_在192.168.17.171,使⽤ab压测⼯具对该端⼝进⾏放量注意:必须使⽤ -k 参数,使⽤keepalived模式下才能模拟出nagle算法root@k8s-node2:~# ab -n 1000 -c 100 -k 127.0.0.1/This is ApacheBench, Version 2.3 <$Revision: 1807734 $>Copyright 1996 Adam Twiss, Zeus Technology Ltd, /Licensed to The Apache Software Foundation, /...Time per request: 44.619 [ms] (mean)...过滤掉⼤量信息,我们来到这个指标Time per request,⽆论怎么测试,平均延时总是在40ms左右我们来看下抓包信息,使⽤wireshark打开在⼤量的数据包中,我们先处理⼀下数据包,随便选取⼀个syn,选取与该syn对应的tcp流选取⼀个⽚段来分析● 在Linux中,默认打开了延迟确认,所谓延迟确认,即不是收到每个请求都发送⼀次ack,⽽是等待⼀段时间,如果这段时间正好有包需要发送,就坐着“顺风车”⼀起发出,否则超时后单独发送。所以客户端会等待40ms,再发送这个ack● 由于nginx也设置了nagle算法,如果没有收到ack,它会等着包的到来,所以就会呈现这个样⼦ (1)192.168.17.171⾸先发送⼀个http get请求(677号包) (2)192.167.17.173发送PSH,ACK(999号包) (3)此时由于Linux默认打开延迟确认,192.168.17.171会等待40ms,看看有没有“顺风车”;⽽192.168.17.173上的nginx由于关闭了tcp_nodelay,它也会等待着ack的到来再回应 (4)40ms过后,192.168.17.171没有等到“顺风车”,此时发送ack(1109号包) (5)192.168.17.173收到ack后发送了http 200(1118号包) (6)192.168.17.171收到数据之后发送确认ack(1127号包)192.168.17.171:47388 192.168.17.173:80 +-------+ +--------+ | | no.677 http get | | | +---------------------------------> | | | | | | | no.999 PSH,ACK | | | <---------------------------------+ | | | | | | | | | | | | | | | delay 40ms | | | | | | | | | | | | | | | | no.1109 ACK | | | +---------------------------------> | | | | | | | no.1118 http 200 | | | <---------------------------------+ | | | | | | | no.1127 ACK | | | +---------------------------------> | | | | | | | | | +-------+ +--------+四、关闭nagle只需要设置tcp_nodelay on;root@k8s-node2:/tmp# sed -i '/tcp_nodelay/s/off/on/g' ot@k8s-node2:/tmp# docker rm -f nginx_delaynginx_delayroot@k8s-node2:/tmp# docker run -d --name nginx_delay -v /tmp/:/etc/nginx/ -p 80:80 nginx:latestbac9bcf7a6e392a7a07afae165c3d5b4e3fb2fc43d3470f35802e12d1e7ae70d再⽤ab测试:root@k8s-node2:~# ab -n 1000 -c 100 -k 127.0.0.1/This is ApacheBench, Version 2.3 <$Revision: 1807734 $>Copyright 1996 Adam Twiss, Zeus Technology Ltd, /Licensed to The Apache Software Foundation, /...Time per request: 14.285 [ms] (mean)...再来观察抓包的结果:● 由于客户端依然打开了延迟确认,所以192.168.17.171收到数据包之后依然没有及时回应● 但是nginx,tcp_nodelay on,所以192.168.17.173收到数据包后会⽴即响应ack● 192.168.17.171收到之后,已经有2个没有确认的数据包了,所以会⽴即发送ack进⾏确认: (1)192.168.17.171⾸先发送⼀个http get请求(447号包) (2)192.168.17.173收到之后⽴即响应psh,ack(740号包) (3)192.168.17.173发送http 200(741号包) (4)192.168.17.171回应ack(742号包)192.168.17.171:49718 192.168.17.173:80 +-------+ +--------+ | | no.447 http get | | | +---------------------------------> | | | | | | | no.740 PSH,ACK | | | <---------------------------------+ | | | | | | | no.741 http 200 | | | <---------------------------------+ | | | | | | | no.742 ACK | | | +---------------------------------> | | | | | | | | | +-------+ +--------+五、⼩结● 本⽂复现了经典的40ms问题● 本⽂中提到了2个名词,nagle算法与延迟确认,它们看上去很相似,但是并不⼀样。nagle算法是需要等到对端ack来临,或者凑满⼀个mss之后才发送数据包;⽽延迟确认针对的是ack,ack会等待“顺风车”,如果有,就乘坐顺风车发送,否则等待超时之后单独发送● 本⽂中延迟确认是Linux默认打开的功能,所以在实验中,客户端都会有延时确认的情况,要关闭客户端延迟确认,需要设置setsockopt中的TCP_QUICKACK● 本⽂中主要讨论的是nginx的nagle算法,nagle算法完全由tcp协议的ack机制决定,如果对端ACK回复很快的话,nagle事实上不会拼接太多的数据包,虽然避免了⽹络拥塞,⽹络总体的利⽤率依然很低● nagle算法在与延迟确认互相作⽤的情况下,会产⽣严重的延时效果,这是需要警惕的● nginx中是否打开nagle算法,要取决于业务场景。⽐如在实验中看到: (1)tcp_nodelay off,会增加通信的延时,但是会提⾼带宽利⽤率。在⾼延时、数据量⼤的通信场景中应该会有不错的效果 (2)tcp_nodelay on,会增加⼩包的数量,但是可以提⾼响应速度。在及时性⾼的通信场景中应该会有不错的效果⾄此,本⽂结束在下才疏学浅,有撒汤漏⽔的,请各位不吝赐教...

发布者:admin,转转请注明出处:http://www.yc00.com/xiaochengxu/1690105602a306254.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信