一、概述

我们之前介绍过一种具有大的带宽时延乘积(band-delay product、BDP)的网络,这种网络称为长肥网络(LongFatNetwork,即LFN)。我们想象一种简单的场景,假设发送端的发送窗口为5000bytes,网络的RTT为200ms,那么每秒的最大速率则为5000*(1000/200)=25000bytes/s,这大约为24kb/s,可以看到这个速率是非常低的,这就是TCP发送窗口对于发送速率的限制,实际的window size应该至少为带宽时延积才能高效的利用网络传输能力。因此对于长肥网络需要扩大TCP的window size,我们之前就已经介绍过RFC1323提高的高性能TCP扩展选项WSOPT,这允许了TCP使用更大的window size(大约是1GB)。但是我们在连接建立初始化的时候很难确切的知道这个这个网络的带宽时延积,这就需要对于window size的一种自动调整(auto-tuning)算法,对于长肥网络能自动抬升TCP的接收缓存,进而增大window size。有时这种接收缓存自动调整技术也称为Dynamic Right-Sizing(DRS)。

二、linux下相关的几个配置参数简单介绍

net.ipv4.tcp_moderate_rcvbuf

这个参数设置为非0,且用户没有通过SO_RCVBUF设置socket对应的接收缓存的时候,那么TCP就会自动调整接收缓存。但是调整的接收窗口最大值不会超过tcp_rmem[2]。这对于长时延高传输速率的网络来说,可以大幅提高接收窗口提高传输速率。

net.core.wmem_max和net.core.rmem_max

这两个参数分别决定了通过SO_SNDBUF和SO_RCVBUF这两个SOCKET选项能设置的最大的发送缓存值和接收缓存值,另外通过SO_SNDBUF和SO_RCVBUF设置的时候还有两个下限,在ubuntu16.04上分别是4608和2304,,还记前前面实例中我们介绍过通过这两个选项设置接收缓存的时候实际上内核会将设置的值先乘2吧,假如通过SO_RCVBUF设置接收缓存为3500,那么内核会max(min(3500*2,rmem_max),2304)=7000,最终将接收缓存设置为7000。

net.ipv4.tcp_adv_win_scale

上面举例中的7000bytes缓存会分为两部分,一部分用于接收窗口的称为内核缓存,这个对应实际的接收的有效TCP数据,另外一部分用于存储这些TCP数据的辅助结构(skb),这部分称为应用缓存,这个是linux的man page的称呼,应用缓存这个称呼好像不是很合适(linux的man page也会有错误的,比如对于tcp_retries2参数的解释就是错的,对于这个应用缓存和内核缓存的解释实在不想吐槽了)。这两部分的比例可以通过tcp_adv_win_scale设置。如果tcp_adv_win_scale>0,则应用缓存占bytes/2^tcp_adv_win_scale,如果这个参数小于0,则应用缓存占bytes- bytes/2^(-tcp_adv_win_scale)。比如设置为tcp_adv_win_scale为2的时候,用于window size的缓存则为7000*(1-1/2^2)=5250bytes。

net.core.wmem_default和net.core.rmem_default

这两个参数指定了传输层协议的默认发送缓存和接收缓存

net.ipv4.tcp_wmem和net.ipv4.tcp_rmem

其中tcp_wmem这个值是由三个整数组成,三个整数分别是min, default, max。min是给每个socket的最小接收缓存的保证值,即使在有内存压力的情况下,如果当前已经真实分配的接收缓存低于min,分配的时候仍然可以分配出内存。default则会覆盖wmem_default,wmem_default指定的是传输层协议的发送缓存默认值,default进一步指定了TCP协议下发送缓存的默认值。比如UDP没有指定自己的发送缓存的默认值那么就会使用wmem_default作为默认值。max则指定了发送缓存的最大值。tcp_rmem这个参数与tcp_wmem类似。

三、wireshark示例

1、缓存自动调整这块在实现上相对复杂一些,这里仅给出一个示例,不再仔细说明调整过程。如下面两张图所示,client端开始每隔5ms写入40bytes的数据,连续写入三次,接着client端在连续写入5次4096bytes的数据,每次写入之间不停顿。可以看到在开始的每次写入40bytes的数据的时候server端的window size一直为2088,在连续大量写入5次4096bytes的数据后,server端开始缓慢增加window size直到最后第49个数据包window size变为43848。

补充说明:

1、http://kb.pert.geant.net/PERTKB/TCPBufferAutoTuning

2、http://patchwork.ozlabs.org/patch/276802/mbox/

3、具体的接收缓存调整算法已经超过本文的介绍范围了,可以参考tcp_rcv_space_adjust、tcp_rcv_rtt_update、tcp_clamp_window、tcp_grow_window

TCP系列34—窗口管理&流控—8、缓存自动调整的更多相关文章

  1. TCP系列27—窗口管理&流控—1、概述

    在前面的内容中我们依次介绍了TCP的连接建立和终止过程和TCP的各种重传方式.接着我们在这部分首先关注交互式应用TCP连接相关内容如延迟ACK.Nagle算法.Cork算法等,接着我们引入流控机制(f ...

  2. TCP系列31—窗口管理&流控—5、TCP流控与滑窗

    一.TCP流控 之前我们介绍过TCP是基于窗口的流量控制,在TCP的发送端会维持一个发送窗口,我们假设发送窗口的大小为N比特,网络环回时延为RTT,那么在网络状况良好没有发生拥塞的情况下,发送端每个R ...

  3. TCP系列33—窗口管理&流控—7、Silly Window Syndrome(SWS)

    一.SWS介绍 前面我们已经通过示例看到如果接收端的应用层一直没有读取数据,那么window size就会慢慢变小最终可能变为0,此时我们假设一种场景,如果应用层读取少量数据(比如十几bytes),接 ...

  4. TCP系列36—窗口管理&流控—10、linux下的异常报文系列接收

    在这篇文章中我们看一下server端在接收到异常数据系列时的处理,主要目的是通过wireshark示例对这些异常数据系列的处理有一个直观的认识,感兴趣的自行阅读相关代码和协议,这里不再进行详细介绍 在 ...

  5. TCP系列35—窗口管理&流控—9、紧急机制

    一.概述 我们在最开始介绍TCP头结构的时候,里面有个URG的标志位,还有一个Urgent Pointer的16bits字段.当URG标志位有效的时候,Urgent Poinert用来指示紧急数据的相 ...

  6. TCP系列32—窗口管理&流控—6、TCP zero windows和persist timer

    一.简介 我们之前介绍过,TCP报文中的window size表示发出这个报文的一端准备多少bytes的数据,当TCP的一端一直接收数据,但是应用层没有及时读取的话,数据一直在TCP模块中缓存,最终受 ...

  7. TCP系列30—窗口管理&流控—4、Cork算法

    一.Cork算法概述 Cork算法与Nagle算法类似,也有人把Cork算法称呼为super-Nagle.Nagle算法提出的背景是网络因为大量小包小包而导致利用率低下产生网络拥塞,网络发生拥塞的时候 ...

  8. TCP系列29—窗口管理&流控—3、Nagle算法

    一.Nagle算法概述 之前我们介绍过,有一些交互式应用会传递大量的小包(称呼为tinygrams),这些小包的负载可能只有几个bytes,但是TCP和IP的基本头就有40bytes,如果大量传递这种 ...

  9. TCP系列28—窗口管理&流控—2、延迟ACK(Delayed Acknowledgments)

    一.简介 之前的内容中我们多次提到延迟ACK(Delayed Ack),延迟ACK是在RFC1122协议中定义的,协议指出,一个TCP实现应该实现延迟ACK,但是ACK不能被过度延迟,协议给出延迟AC ...

随机推荐

  1. PHP 中根据 IP 获取地址

    这里使用的是淘宝 IP 地址库提供的 API 接口. 淘宝 IP 地址库:http://ip.taobao.com/instructions.html API 文档说明:  使用事例: /** * 调 ...

  2. C语言顺序表

    顺序表结构可设为一个数组和一个指向尾部的变量,数组用来存放元素,指向尾部的变量在插入元素的时候加一,删除元素的时候减一,始终指向尾部. typedef int elemtype; typedef st ...

  3. python2和python3的一些区别

    性能:py3.x起始比py2.x效率低,但是py3.x有极大的优化空间,效率正在追赶. 编码:py3原码文件默认utf-8编码,使得变量名更为广阔. 语法:1,去除了 <>  ,改用了  ...

  4. asp.net微信公众平台本地调试设置

    1.首先要开启内网穿透功能,我这边使用自己搭建的ngrok内网穿透服务(具体如何搭建ngrok内网穿透服务,另开一篇说) 2.开启内网穿透后,即可实现互联网访问 www.tbkmama.cn 指向 1 ...

  5. 北京Uber优步司机奖励政策(2月27日)

    滴快车单单2.5倍,注册地址:http://www.udache.com/ 如何注册Uber司机(全国版最新最详细注册流程)/月入2万/不用抢单:http://www.cnblogs.com/mfry ...

  6. 宁波Uber优步司机奖励政策(8月10号-16号)

    本周奖励: 8月10日-8月16日: 滴滴快车单单2.5倍,注册地址:http://www.udache.com/如何注册Uber司机(全国版最新最详细注册流程)/月入2万/不用抢单:http://w ...

  7. 1030: [JSOI2007]文本生成器

    1030: [JSOI2007]文本生成器 https://www.lydsy.com/JudgeOnline/problem.php?id=1030 分析: AC自动机+dp. 正难则反,求满足的, ...

  8. mavn打外部配置jar包依赖

    https://blog.csdn.net/pei19890521/article/details/80984707

  9. 使用Google Cloud Messaging (GCM),PHP 开发Android Push Notifications (安卓推送通知)

    什么是GCM? Google Cloud  Messaging (GCM) 是Google提供的一个服务,用来从服务端向安卓设备发送推送通知. GCM分为客户端和服务端开发. 这里我们只介绍服务端开发 ...

  10. Selenium(Python) ddt读取MySQL数据驱动

    import unittestfrom time import sleep from ddt import ddt, datafrom pymysql import connectfrom selen ...