Linux性能学习(4.4):网络_TCP三次握手内核参数优化

文章目录

  • 1 三次握手
  • 2 参数优化
    • 2.1 tcp_syn_retries--->SYN重传次数
    • 2.2 tcp_synack_retries--->ACK重传次数
    • 2.3 tcp_retries2--->发送数据失败重传次数
    • 2.4 TCP keepalive--->保活机制
    • 2.5 tcp_max_syn_backlog/somaxconn--->半/全连接队列长度
    • 2.6 tcp_syncookies--->cookie机制
    • 2.7 tcp_abort_on_overflow--->RST复位
    • 2.8 tcp_fastopen--->绕过三次握手
  • 3 总结

参考资料:
1. 字节一面:服务端挂了,客户端的 TCP 连接还在吗?

在客户端和服务端建立连接时候,会经过3次交互,才能正式建立一个连接。这篇大致介绍下三次握手的交互过程以及如何优化。

1 三次握手

在这里插入图片描述

  • 第一次交互:Client会发送一个SYN包给到Server,SYN包中包含了Client的一个序列号J,此时Client的状态为SYN_SENT(请求连接状态);
  • 第二次交互:Server收到SYN包后,会返回一个ACK包,用于通知Client收到了SYN包,然后也会给Client发送一个SYN包,用于通知Client自己的序列号为K,此时Server的状态为SYN_RCVD(表示Server已经收到Client的SYN报文);
  • 第三次交互:Client收到Server的ACK+SYN之后,会给Server再次发送一个ACK包,表示已经收到SYN包了,此时Client处于ESTABLISHED状态,Server收到Client的ACK后,也会处于ESTABLISHED状态。

2 参数优化

2.1 tcp_syn_retries—>SYN重传次数

在上面第一次交互时候,Client发送SYN包之后的状态为SYN_SENT,那么此时如果服务器没有收到,即服务端没有返回ACK+SYN报文,会发生什么情况?

如果Client没有收到Server的ACK响应,那么就会多次重传,如果多次重传后,仍然没有收到ACK响应,那么就会返回time out异常。
如下指令查看重传次数:

# cat /proc/sys/net/ipv4/tcp_syn_retries                     
6

重传时的超时时间为,1,2,4,8,16,32,64,逐渐递增,即第一次发送SYN包后,超时1s;进入第1次重传,超时2s;进入第2次重传,超时4s;进入第3次重传,超时8s;进入第4次重传,超时16s;进入第5次重传,超时32s;进入第6次重传,超时64s,上报异常。

因此在某些场景下,如局域网通信,我们可以修改重传次数来减少等待时间,让应用层更快进行处理异常。

2.2 tcp_synack_retries—>ACK重传次数

第二次交互时候,如果Server发送完SYN+ACK,没有收到Client的ACK,又会发生什么情况?
如果没有收到Client的ACK,Server端也会进行重传,重传次数由tcp_synack_retries参数决定。

 # cat /proc/sys/net/ipv4/tcp_synack_retries                  
5

重传时的超时时间为,1,2,4,8,16,32,逐渐递增。

因此在某些场景下,如网络繁忙不稳定,我们可以增大重传次数,减少链路干扰导致的异常。

2.3 tcp_retries2—>发送数据失败重传次数

第三次交互,Client发送完ACK包之后,就处于ESTABLISHED状态,此时如果Server没有收到ACK,就会重传,根据上面的tcp_synack_retries参数,重传5次后,Server断开连接,此时Client端仍然处于ESTABLISHED状态,如果此时Client发送数据,又会发生什么情况?

这种情况下,Server已经没有连接了,肯定是收不到数据的,但是Client不知道,仍然会发送,然后超时,继续发送,超时,重传次数由tcp_retries2 决定。

# cat /proc/sys/net/ipv4/tcp_retries2                        
15

超时时间受内核中TCP_RTO_MAX、TCP_RTO_MIN相关参数限制,15次大约是15分钟,参考链接1:
在这里插入图片描述

2.4 TCP keepalive—>保活机制

如果Client一直不发送数据,那么什么时候才知道Server已经断开了TCP连接?

如果Client没有开启TCP keepalive 机制,那么这种情况下Client就会一直保持TCP连接;如果开启TCP keepalive 机制,那么Client就会定时发送探测报文,根据Server是否回复来得知Server是否断开TCP连接。
相关参数如下:

# cat /proc/sys/net/ipv4/tcp_keepalive_time                  
7200
# cat /proc/sys/net/ipv4/tcp_keepalive_intvl                 
75
# cat /proc/sys/net/ipv4/tcp_keepalive_probes                
9

tcp_keepalive_time为7200s,也就是如果没有任何数据交互,那么就会在7200s之后启动保活,开始发送探测报文;
tcp_keepalive_intvl为75s,表示每次发送的探测报文间隔为75s;
tcp_keepalive_probes为9,也就是9次发送探测报文都没有收到,认为Server已经断开连接,Client就会中断本次连接。
7200+75*9=7875,也就是7875s之后才能真正确认Server已经断开连接。

2.5 tcp_max_syn_backlog/somaxconn—>半/全连接队列长度

在第二次交互中,Server处于SYN_RCV状态,此时处于一个半连接状态,Server会将这个半连接状态的信息放到半连接队列中,如果这个半连接队列满了,那么Server就无法建立新的连接了。

我们可以通过如下指令,查看是否出现半连接队列满的情况:

# netstat -s | grep "SYNs to LISTEN"
332566 SYNs to LISTEN sockets dropped 

如果间隔几秒执行几次,发现这个累加值一直上升,那么说明出现了半连接队列满的情况。

# cat /proc/sys/net/ipv4/tcp_max_syn_backlog                 
128

可以通过调整tcp_max_syn_backlog 的值来修改半连接队列的长度,修改时还需要同步修改somaxconn 的值以及backlog来配合使用。


# cat /proc/sys/net/core/somaxconn 
128

somaxconn表示的是socket监听队列的最大长度,或者说全连接状态队列的长度。
backlog可使用listen 函数的 backlog 参数进行修改。

如果在某些场景下,比如经常处理新的请求的场景,可以修改半连接队列和全连接队列的长度。

2.6 tcp_syncookies—>cookie机制

如果在半连接队列满的情况下,开启了tcp_syncookies,那么Server不会丢弃这个连接,会根据Client的SYN包计算出一个cookie值,将它放到ACK+SYN报文中发送出去,然后收到Client的ACK后,会进行计算验证,如果合法,那么就认为建立连接成功。

# cat /proc/sys/net/ipv4/tcp_syncookies
1

0 表示关闭该功能;1 表示仅当 SYN 半连接队列放不下时,再启用它;2表示无条件开启功能。

2.7 tcp_abort_on_overflow—>RST复位

在第三次交互中,Client发送ACK之后就处于连接状态,而Server收到ACK后会将连接从半连接队列中删除,然后创建新的连接,将其加到全连接队列中。如果此时全连接队列满了,那么就会根据tcp_abort_on_overflow的值进行判定,如果tcp_abort_on_overflow值为0,则丢弃这个ACK;如果值为1,则会回复一个RST复位报文给Client,告诉Client连接已经建立失败,丢弃连接。

# cat /proc/sys/net/ipv4/tcp_abort_on_overflow             
0

2.8 tcp_fastopen—>绕过三次握手

在三次握手中,第三次交互时候,即Client发送ACK回复的时候,ACK中是可以携带HTTP请求的,因此整个交互,是至少需要一个RTT时间(即Client到Server,然后Server到Client的往返时间)才能发送HTTP请求。

问题来了,能否节省这一个RTT时间,进行HTTP请求?

Google提出了TCP fast open方案,使Client可以在第一次交互时候Client发送的SYN报文中直接携带请求,这样就可以节省了一个RTT时间。
具体是分为两个步骤进行的:

  • 第一个步骤:正常的三次握手机制,只不过在Client发送SYN报文时候,包含了Fast Open选项,选项中的Cookie为空,然后支持Fast Open的Server收到SYN报文后,会生成一个cookie,放进ACK+SYN报文中,然后ACK收到报文,缓存cookie到本地。
  • 第二个步骤:如果下次再次向Server建立连接,那么在第一次交互时候,Client发送的SYN报文中包含HTTP请求和第一个步骤中缓存的cookie,Server收到SYN报文后,会对cookie进行验证,如果验证成功,则HTTP请求数据有效,送到对应的处理程序中,如果请求无效则丢弃HTTP请求数据。不管是否有效,都会回复ACK+SYN报文,Client也会再次回复ACK。但是,这种如果有效,那么在第一次交互时候,SYN包中已经携带有效数据了,省了一个RTT时间。
# cat /proc/sys/net/ipv4/tcp_fastopen                        
1

0:关闭1:作为客户端使用 Fast Open 功能2:作为服务端使用 Fast Open 功能3:无论作为客户端还是服务器,都可以使用 Fast Open 功能。
TCP Fast Open 功能需要客户端和服务端同时支持,才有效果。

3 总结

在本篇中,引申出以下几个内核参数,除了tcp_retries2和tcp_keepalive_time外,其它内核参数均是和三次握手相关的。
在这里插入图片描述

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

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

相关文章

[CSS] 图片九宫格

效果 index.html <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"/><meta http-equiv"X-UA-Compatible" content"IEedge"/><meta name"viewport" content"widthdevice-…

SpringBoot第30讲:SpringBoot集成MySQL - MyBatis-Plus基于字段隔离的多租户

SpringBoot第30讲&#xff1a;SpringBoot集成MySQL - MyBatis-Plus基于字段隔离的多租户 本文是SpringBoot第30讲&#xff0c;主要介绍 MyBatis-Plus的基于字段隔离的多租户实现&#xff0c;以及MyBatis-Plus的基于字段的隔离方式实践和原理。 文章目录 SpringBoot第30讲&#…

bash的特性(二)IO重定向与管道

bash的I/O重定向及管道 一、概述 在shell中&#xff0c;最常使用的fd(file descriptor)有三个&#xff0c;标准输入&#xff0c;标准输出&#xff0c;错误输出。进程用文件描述符来管理打开的文件。 名称 文件描述符 标准输入&#xff08;stdin) 0 键盘&#xff0c;也可以…

pom文件---maven

027-Maven 命令行-实验四-生成 Web 工程-执行生成_ev_哔哩哔哩_bilibili 27节.后续补充 一.maven下载安装及配置 1)maven下载 2) settings文件配置本地仓库 3)settings配置远程仓库地址 4)配置maven工程的基础JDK版本 5)确认JDK环境变量配置没问题,配置maven的环境变量 验证…

K8s实战入门(三)

文章目录 3. 实战入门3.1 Namespace3.1.1 测试两个不同的名称空间之间的 Pod 是否连通性 3.2 Pod3.3 Label3.4 Deployment3.5 Service 3. 实战入门 本章节将介绍如何在kubernetes集群中部署一个nginx服务&#xff0c;并且能够对其进行访问。 3.1 Namespace Namespace是kuber…

flask-----蓝图

1.引入蓝图 flask都写在一个文件中&#xff0c;项目这样肯定不行&#xff0c;会导致循环导入的问题&#xff0c;分目录&#xff0c;分包&#xff0c;使用蓝图划分目录。 2.使用蓝图 步骤如下&#xff1a; -1 实例化得到一个蓝图对象-order_blueBlueprint(order,__name__,tem…

uniapp echarts 点击失效

这个问题网上搜了一堆&#xff0c;有的让你降版本&#xff0c;有的让你改源码。。。都不太符合预期&#xff0c;目前我的方法可以用最新的echarts。 这个方法就是由npm安装转为CDN&#xff0c;当然你可能会质疑用CDN这样会不稳定&#xff0c;那如果CDN的地址是本地呢&#xff1…

Button按钮(antd-design组件库)简单使用

1.Button按钮 按钮用于开始一个即时操作。 2.何时使用 标记了一个&#xff08;或封装一组&#xff09;操作命令&#xff0c;响应用户点击行为&#xff0c;触发相应的业务逻辑。 在 Ant Design 中我们提供了五种按钮。 主按钮&#xff1a;用于主行动点&#xff0c;一个操作区域只…

无涯教程-Lua - nested语句函数

Lua编程语言允许在另一个循环中使用一个循环。以下部分显示了一些示例来说明这一概念。 nested loops - 语法 Lua中嵌套for循环语句的语法如下- for init,max/min value, increment dofor init,max/min value, incrementdostatement(s)endstatement(s) end Lua编程语言中的…

Kernel Exception导致手机重启案例分析

和你一起终身学习&#xff0c;这里是程序员Android 经典好文推荐&#xff0c;通过阅读本文&#xff0c;您将收获以下知识点: 一、高温触发 Kernel Exception 重启问题二、解决方案三、提高电池温度方案 一、 高温触发 Kernel Exception 重启问题 手机 电池温度 默认60度以上高温…

MySQL索引3——Explain关键字和索引使用规则(SQL提示、索引失效、最左前缀法则)

目录 Explain关键字 索引性能分析 Id ——select的查询序列号 Select_type——select查询的类型 Table——表名称 Type——select的连接类型 Possible_key ——显示可能应用在这张表的索引 Key——实际用到的索引 Key_len——实际索引使用到的字节数 Ref ——索引命…

【BASH】回顾与知识点梳理(七)

【BASH】回顾与知识点梳理 七 七. 前六章知识点总结及练习7.1 总结7.2 练习 该系列目录 --> 【BASH】回顾与知识点梳理&#xff08;目录&#xff09; 七. 前六章知识点总结及练习 7.1 总结 由于核心在内存中是受保护的区块&#xff0c;因此我们必须要透过『 Shell 』将我…