网络传输,请每次都开启 TCP_NODELAY

在这里插入图片描述

原文:Marc Brooker - 2024.05.09

(注:不必过于担心这个问题,大部分现代库,语言(如 Go),代理(如 Envoy),都默认设置了 TCP_NODELAY。如果遇到网络延迟问题,可再检查该套接字选项。)

我们已经不再生活在上世纪 80 年代了,谢天谢地!

在调试分布式系统的延迟问题时,我首先检查的就是 TCP_NODELAY 是否启用。不仅仅是我,我认识的每个分布式系统构建者,都曾因为启用了这个简单的套接字选项而迅速修复了延迟问题,这说明默认行为是错误的,也许整个概念都过时了。

首先,要明确我们在讨论什么。没有比 John Nagle 1984 年的 RFC896 更好的资料来源了。下面是问题陈述:

有一个与小数据包相关的特殊问题。当 TCP 用于传输源自键盘的单字符信息时,典型的结果是每传输一个字节的有效数据,就要传输 41 个字节的数据包(1 个字节的数据,40 个字节的报头)。这 4000% 的开销虽然令人讨厌,但在负载较低的网络中还是可以忍受的。

简单地说,Nagle 想要更好地摊销 TCP 报头的成本,以便从网络中获得更好的吞吐量。吞吐量最多可提高 40 倍!造成这些微小数据包的主要原因有两个:一是像 shell 这样的人机交互应用程序,人们一次只输入一个字节;二是程序的实现不佳,通过多次 write 调用向内核发送信息。Nagle 提出的解决的方案既简单又聪明:

我们已经找到了一个简单且优雅的解决方案。

这个解决方案就是,当用户发送新数据时,如果网络连接上之前传输的任何数据仍未被确认,则禁止发送新的 TCP 段。

很多人在谈到 Nagle 算法时都会提到计时器,但 RFC896 并没有使用除网络往返时间以外的任何计时器。

Nagle 的算法与延迟确认

Nagle 清晰、简洁的提案与另一个 TCP 功能交互不畅:延迟确认。延迟确认背后的理念是延迟发送对数据包的确认,至少要等到有数据要回传(例如 telnet 会话回传用户输入的内容),或者等到计时器到期。1982 年的 RFC813 似乎是第一个提出延迟确认的文件:

数据接收方在某些情况下将不发送 ACK,在这种情况下,接收方必须设置一个计时器,使 ACK 在稍后发送。不过,接收方只有在可以合理推测会有其他事件介入,从而避免定时器中断的情况下,才应该这样做。

随后,在 1989 年的 RFC1122 中,得到了进一步的正式规定。这两个特性之间的相互作用引发了一个问题:Nagle 算法会阻止发送更多数据,直到收到一个 ACK;而延迟确认则会延迟该 ACK,直到准备好一个响应。这对于保持数据包满载很有帮助,但对于延迟敏感的高并发应用就没那么好了。

这也是 Nagle 自己多次提出的观点。例如在这个 Hacker News 评论 中:

这仍然让我感到恼火。真正的问题不是防止小报文。而是 ACK 延迟和那个愚蠢的固定计时器。这两个问题大约同时出现在 TCP 中,但各自独立。在 1980 年代初,我做了小报文优化的 Nagle 算法,伯克利做了延迟确认。两者的结合非常糟糕。

作为系统建设者,这种情况应该不陌生:系统中两个合理的特性相互作用,产生了不良行为。这种相互作用正是协议设计之所以如此困难的原因之一。

Nagle 算法真的无可指责吗?

遗憾的是,问题不仅仅在于延迟确认。即使没有延迟确认和那个愚蠢的固定定时器,在分布式系统中,Nagle 算法的行为可能也不是我们想要的。单个数据中心内的 RTT 通常约为 500 微秒,同一区域内的数据中心之间为几毫秒,全球范围内则高达数百毫秒。考虑到现代服务器在几百微秒内就能完成大量工作,即使延迟一个 RTT 发送数据也不会有明显的优势。

为了更清楚地说明这一点,让我们回到 Nagle 算法背后的理由:摊销报头成本,避免单字节数据包的 40 倍开销。但现在还有人发送单字节数据包吗?大多数分布式数据库和系统都不会。部分原因是它们有更多的数据,部分原因是 TLS 等协议的额外开销,部分原因是编码和序列化开销。但最主要的是,它们有更多的内容和数据。

不发送微小信息的核心问题依然存在,但我们已经非常有效地将其推向了应用层。无论 Nagle 算法如何处理,一次发送一个用 JSON 封装的字节都不会非常高效。

还需要 Nagle 算法吗?

首先,没有争议的观点是:如果你正在构建一个对延迟敏感的分布式系统,并在现代数据中心级别的硬件上运行,那么请放心启用 TCP_NODELAY(禁用 Nagle 算法)。你不必感到难过,这不是罪过。没关系,放手去做吧。

更有争议的是,考虑到流量和应用程序的组合,以及我们今天所拥有的硬件能力,我怀疑现代系统并不需要 Nagle 算法。换句话说,TCP_NODELAY 应该是默认设置。这将使一些“写入每个字节”的代码变得比原来更慢,但如果我们关心效率,无论如何都应该是修复这些应用。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/701255.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

6. 第K小的和-二分

6.第K小的和 - 蓝桥云课 (lanqiao.cn) #include <bits/stdc.h> #define int long long #define endl \n using namespace std; int n,m,k,an[100005],bm[100005]; int check(int x){int res0;//序列C中<x的数的个数for(int i0;i<n;i){//遍历数组A&#xff0c;对于每…

工厂数字化转型实现路线

工厂数字化转型实现路线 随着科技的飞速发展&#xff0c;数字化转型已成为当今社会的热门话题。尤其是对于工厂企业而言&#xff0c;数字化转型更是一种必然趋势。然而&#xff0c;在这个过程中&#xff0c;许多企业面临着种种困难和挑战。因此&#xff0c;探讨工厂企业数字化转…

练习题(2024/5/13)

1移除链表元素 给你一个链表的头节点 head 和一个整数 val &#xff0c;请你删除链表中所有满足 Node.val val 的节点&#xff0c;并返回 新的头节点 。 示例 1&#xff1a; 输入&#xff1a;head [1,2,6,3,4,5,6], val 6 输出&#xff1a;[1,2,3,4,5]示例 2&#xff1a; …

如何对基本公共服务均等化进行统计监测

党的十九大指出“履行好政府再分配调节职能&#xff0c;加快推进基本公共服务均等化&#xff0c;缩小收入分配差距”&#xff0c;提出到2035年基本公共服务均等化基本实现。国务院相继于2012年和2017年发布了《国家基本公共服务体系“十二五”规划》和《“十三五”推进基本公共…

基于安装包安装数据库时出现的问题分析及总结

数据库在数据初始化后并不会出现错误&#xff0c;这个时候在启动数据库时会出现启动不成功&#xff0c;不知道问题是什么要学会通过查看日志发现问题&#xff0c;日志就在Data文件夹下。 错误类型1 数据库在初始化后数据库启动不起来 原因&#xff1a;可能是配置文件my.ini一些…

深入探索内存映射:mmap和共享内存的工作原理及区别

目录标题 1. 引言 1.1 内存映射的定义1.2 mmap 系统调用概述 2. 内存映射基础 2.1 内存映射的定义2.2 mmap 系统调用概述2.3 mmap 系统调用和直接使用IPC共享内存之间的差异 3. mmap 与文件 I/O 3.1. 传统文件 I/O 的局限性3.2. mmap 的优势 4. 内存映射的工作原理&…

力扣HOT100 - 198. 打家劫舍

解题思路&#xff1a; 动态规划 class Solution {public int rob(int[] nums) {int len nums.length;if (nums null || len 0) return 0;if (len 1) return nums[0];int[] dp new int[len];dp[0] nums[0];dp[1] Math.max(nums[0], nums[1]);for (int i 2; i < len;…

智能AI数字人系统 打造无人直播间 主播形象任意选择!

系统概述 智能AI数字人系统是一种结合人工智能、计算机图形学、语音合成等技术的综合性系统。该系统能够模拟人类的外貌、行为和语言&#xff0c;为用户提供逼真的交互体验。在无人直播间场景下&#xff0c;智能AI数字人系统可以扮演主播角色&#xff0c;与观众进行实时互动&a…

AIConnect 综合算力服务网络:引领智能未来,创造无限可能性!

2022年11月30日&#xff0c;由OpenAI开发的大模型聊天机器人GPT-3发布&#xff0c;首个完全意义上通过图灵测试的人工智能诞生了。这一里程碑事件的启发了人们对AI技术的发展和应用。在短短两年的时间里&#xff0c;各式各样的聊天AI&#xff0c;图片生成AI&#xff0c;视频生成…

Springboot+MybatisPlus如何实现分页和模糊查询

实现分页查询的时候我们需要创建一个config配置类 1、创建MybatisPlusConfig类 Configuration //表明这是一个配置类 ConditionalOnClass(Value{PaginationInterceptor.class} //ConditionalOnClass:当指定的类存在时&#xff0c;才会创建对应的Bean // 这里当PaginationInt…

【Linux】用户组、用户、文件权限(ugo权限),权限掩码,chmod,chown,suid,sgid,sticky,su,sudo

用户组 注意&#xff1a;普通用户只能查看有哪些组&#xff0c;不能创建/修改/删除&#xff0c;会提示&#xff1a;用户名 is not in the sudoers file.This incident will be reported. groupadd 用户组名新建用户组cat /etc/group查看有哪些组&#xff08;普通用户可以操作…

性能测试学习二

瓶颈的精准判断 TPS曲线 tps图 响应时间图 拐点在哪里呢? 这是一个阶梯式增加的场景,拐点在第二个压力阶梯上就出现了,因为响应时间增加了,tps增加的却不多,在第三个阶段时,tps增加的就更少了,响应时间也在不断增加,所以性能瓶颈在加剧,越往后越明显【tps的增长,…