首页 > 其他分享 >夯实基础之tcp优化传输数据性能

夯实基础之tcp优化传输数据性能

时间:2022-09-29 17:24:24浏览次数:52  
标签:窗口 夯实 报文 TCP 发送 传输数据 内存 tcp

tcp传输数据性能提升

在前面介绍的是三次握手和四次挥手的优化策略,接下来主要介绍的是 TCP 传输数据时的优化策略。

TCP 连接是由内核维护的,内核会为每个连接建立内存缓冲区:

如果连接的内存配置过小,就无法充分使用网络带宽,TCP 传输效率就会降低;
如果连接的内存配置过大,很容易把服务器资源耗尽,这样就会导致新连接无法建立;
因此,我们必须理解 Linux 下 TCP 内存的用途,才能正确地配置内存大小

滑动窗口是如何影响传输速度的?
TCP 会保证每一个报文都能够抵达对方,它的机制是这样:报文发出去后,必须接收到对方返回的确认报文 ACK,如果迟迟未收到,就会超时重发该报文,直到收到对方的 ACK 为止。

所以,TCP 报文发出去后,并不会立马从内存中删除,因为重传时还需要用到它。

由于 TCP 是内核维护的,所以报文存放在内核缓冲区。如果连接非常多,我们可以通过 free 命令观察到 buff/cache 内存是会增大。

如果 TCP 是每发送一个数据,都要进行一次确认应答。当上一个数据包收到了应答了, 再发送下一个。这个模式就有点像我和你面对面聊天,你一句我一句,但这种方式的缺点是效率比较低的。
所以,这样的传输方式有一个缺点:数据包的往返时间越长,通信的效率就越低。

要解决这一问题不难,并行批量发送报文,再批量确认报文即可。
然而,这引出了另一个问题,发送方可以随心所欲的发送报文吗?当然这不现实,我们还得考虑接收方的处理能力。

当接收方硬件不如发送方,或者系统繁忙、资源紧张时,是无法瞬间处理这么多报文的。于是,这些报文只能被丢掉,使得网络效率非常低。

为了解决这种现象发生,TCP 提供一种机制可以让「发送方」根据「接收方」的实际接收能力控制发送的数据量,这就是滑动窗口的由来。

接收方根据它的缓冲区,可以计算出后续能够接收多少字节的报文,这个数字叫做接收窗口。当内核接收到报文时,必须用缓冲区存放它们,这样剩余缓冲区空间变小,接收窗口也就变小了;当进程调用 read 函数后,数据被读入了用户空间,内核缓冲区就被清空,这意味着主机可以接收更多的报文,接收窗口就会变大。

因此,接收窗口并不是恒定不变的,接收方会把当前可接收的大小放在 TCP 报文头部中的窗口字段,这样就可以起到窗口大小通知的作用。

发送方的窗口等价于接收方的窗口吗?如果不考虑拥塞控制,发送方的窗口大小「约等于」接收方的窗口大小,因为窗口通知报文在网络传输是存在时延的,所以是约等于的关系。
窗口字段只有 2 个字节,因此它最多能表达 65535 字节大小的窗口,也就是 64KB 大小。

这个窗口大小最大值,在当今高速网络下,很明显是不够用的。所以后续有了扩充窗口的方法:在 TCP 选项字段定义了窗口扩大因子,用于扩大 TCP 通告窗口,其值大小是 2^14,这样就使 TCP 的窗口大小从 16 位扩大为 30 位(2^16 * 2^ 14 = 2^30),所以此时窗口的最大值可以达到 1GB。
Linux 中打开这一功能,需要把 tcp_window_scaling 配置设为 1(默认打开):

[root@k8s-master ~]# cat /proc/sys/net/ipv4/tcp_window_scaling 
1
[root@k8s-master ~]# 

要使用窗口扩大选项,通讯双方必须在各自的 SYN 报文中发送这个选项:

主动建立连接的一方在 SYN 报文中发送这个选项;
而被动建立连接的一方只有在收到带窗口扩大选项的 SYN 报文之后才能发送这个选项。
这样看来,只要进程能及时地调用 read 函数读取数据,并且接收缓冲区配置得足够大,那么接收窗口就可以无限地放大,发送方也就无限地提升发送速度。

这是不可能的,因为网络的传输能力是有限的,当发送方依据发送窗口,发送超过网络处理能力的报文时,路由器会直接丢弃这些报文。因此,缓冲区的内存并不是越大越好

在 Linux 中发送缓冲区和接收缓冲都是可以用参数调节的。设置完后,Linux 会根据你设置的缓冲区进行动态调节。

调节发送缓冲区范围

先来看看发送缓冲区,它的范围通过 tcp_wmem 参数配置;

[root@k8s-master ~]# cat /proc/sys/net/ipv4/tcp_wmem 
4096	16384	4194304
[root@k8s-master ~]# 

上面三个数字单位都是字节,它们分别表示:

第一个数值是动态范围的最小值,4096 byte = 4K;
第二个数值是初始默认值,16384 byte ≈ 16K;
第三个数值是动态范围的最大值,4194304 byte = 4096K(4M);
发送缓冲区是自行调节的,当发送方发送的数据被确认后,并且没有新的数据要发送,就会把发送缓冲区的内存释放掉。

调节接收缓冲区范围

而接收缓冲区的调整就比较复杂一些,先来看看设置接收缓冲区范围的 tcp_rmem 参数:

[root@k8s-master ~]# cat /proc/sys/net/ipv4/tcp_rmem 
4096	87380	6291456
[root@k8s-master ~]# 

上面三个数字单位都是字节,它们分别表示:

第一个数值是动态范围的最小值,表示即使在内存压力下也可以保证的最小接收缓冲区大小,4096 byte = 4K;
第二个数值是初始默认值,87380 byte ≈ 86K;
第三个数值是动态范围的最大值,6291456 byte = 6144K(6M);
接收缓冲区可以根据系统空闲内存的大小来调节接收窗口:

如果系统的空闲内存很多,就可以自动把缓冲区增大一些,这样传给对方的接收窗口也会变大,因而提升发送方发送的传输数据数量;
反之,如果系统的内存很紧张,就会减少缓冲区,这虽然会降低传输效率,可以保证更多的并发连接正常工作;
发送缓冲区的调节功能是自动开启的,而接收缓冲区则需要配置 tcp_moderate_rcvbuf 为 1 来开启调节功能:

[root@k8s-master ~]# cat /proc/sys/net/ipv4/tcp_moderate_rcvbuf 
1
[root@k8s-master ~]#

调节 TCP 内存范围

接收缓冲区调节时,怎么知道当前内存是否紧张或充分呢?这是通过 tcp_mem 配置完成的:

[root@k8s-master ~]# cat /proc/sys/net/ipv4/tcp_mem
88566	118089	177132
[root@k8s-master ~]#

上面三个数字单位不是字节,而是「页面大小」,1 页表示 4KB,它们分别表示:

当 TCP 内存小于第 1 个值时,不需要进行自动调节;
在第 1 和第 2 个值之间时,内核开始调节接收缓冲区的大小;
大于第 3 个值时,内核不再为 TCP 分配新内存,此时新连接是无法建立的;
一般情况下这些值是在系统启动时根据系统内存数量计算得到的。根据当前 tcp_mem 最大内存页面数是 177120,当内存为 (177120 * 4) / 1024K ≈ 692M 时,系统将无法为新的 TCP 连接分配内存,即 TCP 连接将被拒绝。

根据实际场景调节的策略

在高并发服务器中,为了兼顾网速与大量的并发连接,我们应当保证缓冲区的动态调整的最大值达到带宽时延积,而最小值保持默认的 4K 不变即可。而对于内存紧张的服务而言,调低默认值是提高并发的有效手段。

同时,如果这是网络 IO 型服务器,那么,调大 tcp_mem 的上限可以让 TCP 连接使用更多的系统内存,这有利于提升并发能力。需要注意的是,tcp_wmem 和 tcp_rmem 的单位是字节,而 tcp_mem 的单位是页面大小。而且,千万不要在 socket 上直接设置 SO_SNDBUF 或者 SO_RCVBUF,这样会关闭缓冲区的动态调整功能

标签:窗口,夯实,报文,TCP,发送,传输数据,内存,tcp
From: https://www.cnblogs.com/aiverhua/p/16742270.html

相关文章

  • TCP Dup ACK linux kernel 3.2
    ​ TheProblemYourthroughputissuesappeartobecausedbyabuggyimplementationofTCPSequenceNumberrandomization.IhaveseenthisinthepastonCisco......
  • 夯实基础之tcp优化四次挥手性能
    TCP四次挥手的性能提升接下来,我们一起看看针对TCP四次挥手关闭连接时,如何优化性能。在开始之前,我们得先了解四次挥手状态变迁的过程。客户端和服务端双方都可以主......
  • TCP Server
    TCP服务器(单客户端)1.获取本地主机的IP和端口号若本地主机有多个IP地址,则需要获取本地主机所有IP地址,指定某个IP地址用于创建服务器。 char**addresses=NULL; char......
  • TCP和UDP有啥区别?
    TCP全称:TransmissionControlProtocol中文名:传输控制协议解释:是一种面向连接的、可靠的、基于字节流的传输层通信协议,由IETF的RFC793定义。用途:TCP旨在适应支持多......
  • Linux 网络编程——TCP 和 UDP 数据报格式详解
    TCP报文格式TCP(TransmissionControlProtocol传输控制协议)是一种面向连接的、可靠的、基于字节流的传输层通信协议。TCP报文段的报头有10个必需的字段和1个可选字段......
  • HTTP、TCP、UDP以及SOCKET之间的区别/联系
    原文:https://zhuanlan.zhihu.com/p/433976897https://blog.csdn.net/weixin_33465519/article/details/124055757TCP/IP代表传输控制协议/网际协议,指的是一系列协议。可......
  • Netty实战:Netty优雅的创建高性能TCP服务器(附源码)
    文章目录前言1.前置准备2.消息处理器3.重写通道初始化类4.核心服务5.效果预览6.添加通道管理,给指定的客户端发送消息7.源码分享 前言Springbo......
  • TCP三次握手(通俗易懂)
    一--导读TCP服务器的传输控制块: 指向发送和接收缓存的指针(管发和收的人)指向重传队列的指针(重新发送的人)当前的发送和接收序号(管现在发多少和收多少的人)  二---TCP连接要......
  • TCP协议
    一.TCP协议传输控制协议(TCP,TransmissionControlProtocol)是一种面向连接的、可靠的、基于字节流的传输层通信协议。特点:1)基于流的方式;(2)面向连接;(在通信之前要通过三次......
  • 3.TCP-IP & Linux 模型简介
    Dearall,  更新一节Linux网络驱动视频——3.TCP-IP&Linux模型简介,下节课开始正式编写driver。  B站链接:https://www.bilibili.com/video/BV1DG4y1s7ad/?vd_......