阿里云-云小站(无限量代金券发放中)
【腾讯云】云服务器、云数据库、COS、CDN、短信等热卖云产品特惠抢购

Nginx 参数 tcp_nodelay 详解

604次阅读
没有评论

共计 4369 个字符,预计需要花费 11 分钟才能阅读完成。

一、知识准备

  • 在 nginx 优化中有个经常需要设置的参数,tcp_nodelay
  • 该参数最核心的功能,就是把小包组成成大包,提高带宽利用率也就是著名的 nagle 算法
  • tcp 协议中,有一个现象:应用层数据可能很低(比如 1 个字节),而传输层开销有 40 字节 (20 字节的 IP 头 +20 字节的 TCP 头)。这种情况下大部分都是控制包的传输,既加大了带宽的消耗,带宽利用率也不高
  • nagle 算法就是为了解决这个问题。在发出去的数据还未被确认之前,或者说还没有收到对端的 ack 之前,新生成的小包是不允许被发送的,必须要凑满一个 MSS 或者等到收到确认后再发送,直至超时

二、环境准备

组件 版本
OS Ubuntu 18.04.1 LTS
docker 18.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 nginx.conf
user  nginx;
worker_processes  1;

error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;


events {worker_connections  1024;
}


http {include       /etc/nginx/mime.types;
    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/access.log  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/nginx.conf:/etc/nginx/nginx.conf -p 80:80 nginx:latest
6b7d5a5d3c3ed021fed6847d138837754c5732979d1c829ec62107ec80440db8
root@k8s-node2:/tmp# docker ps | grep nginx_delay
6b7d5a5d3c3e        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_ab.cap

在 192.168.17.171,使用 ab 压测工具对该端口进行放量

注意:必须使用 -k 参数,使用 keepalived 模式下才能模拟出 nagle 算法

root@k8s-node2:~# ab -n 1000 -c 100 -k http://127.0.0.1/
This is ApacheBench, Version 2.3 <$Revision: 1807734 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

...
Time per request:       44.619 [ms] (mean)
...

过滤掉大量信息,我们来到这个指标 Time per request,无论怎么测试,平均延时总是在 40ms 左右

我们来看下抓包信息,使用 wireshark 打开

在大量的数据包中,我们先处理一下数据包,随便选取一个 syn,选取与该 syn 对应的 tcp 流

Nginx 参数 tcp_nodelay 详解

选取一个片段来分析

Nginx 参数 tcp_nodelay 详解

● 在 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' nginx.conf
root@k8s-node2:/tmp# docker rm -f nginx_delay
nginx_delay
root@k8s-node2:/tmp# docker run -d --name nginx_delay -v /tmp/nginx.conf:/etc/nginx/nginx.conf -p 80:80 nginx:latest
bac9bcf7a6e392a7a07afae165c3d5b4e3fb2fc43d3470f35802e12d1e7ae70d

再用 ab 测试:

root@k8s-node2:~# ab -n 1000 -c 100 -k http://127.0.0.1/
This is ApacheBench, Version 2.3 <$Revision: 1807734 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

...
Time per request:       14.285 [ms] (mean)
...

再来观察抓包的结果:

Nginx 参数 tcp_nodelay 详解

● 由于客户端依然打开了延迟确认,所以 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,会增加小包的数量,但是可以提高响应速度。在及时性高的通信场景中应该会有不错的效果

正文完
星哥玩云-微信公众号
post-qrcode
 0
星锅
版权声明:本站原创文章,由 星锅 于2022-01-21发表,共计4369字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
【腾讯云】推广者专属福利,新客户无门槛领取总价值高达2860元代金券,每种代金券限量500张,先到先得。
阿里云-最新活动爆款每日限量供应
评论(没有评论)
验证码
【腾讯云】云服务器、云数据库、COS、CDN、短信等云产品特惠热卖中

星哥玩云

星哥玩云
星哥玩云
分享互联网知识
用户数
4
文章数
19351
评论数
4
阅读量
7981182
文章搜索
热门文章
星哥带你玩飞牛NAS-6:抖音视频同步工具,视频下载自动下载保存

星哥带你玩飞牛NAS-6:抖音视频同步工具,视频下载自动下载保存

星哥带你玩飞牛 NAS-6:抖音视频同步工具,视频下载自动下载保存 前言 各位玩 NAS 的朋友好,我是星哥!...
星哥带你玩飞牛NAS-3:安装飞牛NAS后的很有必要的操作

星哥带你玩飞牛NAS-3:安装飞牛NAS后的很有必要的操作

星哥带你玩飞牛 NAS-3:安装飞牛 NAS 后的很有必要的操作 前言 如果你已经有了飞牛 NAS 系统,之前...
我把用了20年的360安全卫士卸载了

我把用了20年的360安全卫士卸载了

我把用了 20 年的 360 安全卫士卸载了 是的,正如标题你看到的。 原因 偷摸安装自家的软件 莫名其妙安装...
再见zabbix!轻量级自建服务器监控神器在Linux 的完整部署指南

再见zabbix!轻量级自建服务器监控神器在Linux 的完整部署指南

再见 zabbix!轻量级自建服务器监控神器在 Linux 的完整部署指南 在日常运维中,服务器监控是绕不开的...
飞牛NAS中安装Navidrome音乐文件中文标签乱码问题解决、安装FntermX终端

飞牛NAS中安装Navidrome音乐文件中文标签乱码问题解决、安装FntermX终端

飞牛 NAS 中安装 Navidrome 音乐文件中文标签乱码问题解决、安装 FntermX 终端 问题背景 ...
阿里云CDN
阿里云CDN-提高用户访问的响应速度和成功率
随机文章
再见zabbix!轻量级自建服务器监控神器在Linux 的完整部署指南

再见zabbix!轻量级自建服务器监控神器在Linux 的完整部署指南

再见 zabbix!轻量级自建服务器监控神器在 Linux 的完整部署指南 在日常运维中,服务器监控是绕不开的...
安装并使用谷歌AI编程工具Antigravity(亲测有效)

安装并使用谷歌AI编程工具Antigravity(亲测有效)

  安装并使用谷歌 AI 编程工具 Antigravity(亲测有效) 引言 Antigravity...
【1024程序员】我劝你赶紧去免费领一个AWS、华为云等的主机

【1024程序员】我劝你赶紧去免费领一个AWS、华为云等的主机

【1024 程序员】我劝你赶紧去免费领一个 AWS、华为云等的主机 每年 10 月 24 日,程序员们都会迎来...
免费领取huggingface的2核16G云服务器,超简单教程

免费领取huggingface的2核16G云服务器,超简单教程

免费领取 huggingface 的 2 核 16G 云服务器,超简单教程 前言 HuggingFace.co...
星哥带你玩飞牛NAS-4:飞牛NAS安装istore旁路由,家庭网络升级的最佳实践

星哥带你玩飞牛NAS-4:飞牛NAS安装istore旁路由,家庭网络升级的最佳实践

星哥带你玩飞牛 NAS-4:飞牛 NAS 安装 istore 旁路由,家庭网络升级的最佳实践 开始 大家好我是...

免费图片视频管理工具让灵感库告别混乱

一言一句话
-「
手气不错
你的云服务器到底有多强?宝塔跑分告诉你

你的云服务器到底有多强?宝塔跑分告诉你

你的云服务器到底有多强?宝塔跑分告诉你 为什么要用宝塔跑分? 宝塔跑分其实就是对 CPU、内存、磁盘、IO 做...
安装并使用谷歌AI编程工具Antigravity(亲测有效)

安装并使用谷歌AI编程工具Antigravity(亲测有效)

  安装并使用谷歌 AI 编程工具 Antigravity(亲测有效) 引言 Antigravity...
星哥带你玩飞牛NAS-13:自动追番、订阅下载 + 刮削,动漫党彻底解放双手!

星哥带你玩飞牛NAS-13:自动追番、订阅下载 + 刮削,动漫党彻底解放双手!

星哥带你玩飞牛 NAS-13:自动追番、订阅下载 + 刮削,动漫党彻底解放双手! 作为动漫爱好者,你是否还在为...
每天一个好玩的网站-手机博物馆-CHAZ 3D Experience

每天一个好玩的网站-手机博物馆-CHAZ 3D Experience

每天一个好玩的网站 - 手机博物馆 -CHAZ 3D Experience 一句话介绍:一个用 3D 方式重温...
把小米云笔记搬回家:飞牛 NAS 一键部署,小米云笔记自动同步到本地

把小米云笔记搬回家:飞牛 NAS 一键部署,小米云笔记自动同步到本地

把小米云笔记搬回家:飞牛 NAS 一键部署,小米云笔记自动同步到本地 大家好,我是星哥,今天教大家在飞牛 NA...