Pages

Sunday, 5 May 2013

修改Linux内核的TCP/IP调优参数

本文详细介绍Linux内核: 修改TCP/IP调优参数
所有的TCP/IP调优参数都位于/proc/sys/net/目录. 例如, 下面是最重要的一些调优参数, 后面是它们的含义:
1. /proc/sys/net/core/rmem_max — 最大的TCP数据接收缓冲
2. /proc/sys/net/core/wmem_max — 最大的TCP数据发送缓冲
3. /proc/sys/net/ipv4/tcp_timestamps — 时间戳在(请参考RFC 1323)TCP的包头增加12个字节
4. /proc/sys/net/ipv4/tcp_sack — 有选择的应答
5. /proc/sys/net/ipv4/tcp_window_scaling — 支持更大的TCP窗口. 如果TCP窗口最大超过65535(64K), 必须设置该数值为1
6. rmem_default — 默认的接收窗口大小
7. rmem_max — 接收窗口的最大大小
8. wmem_default — 默认的发送窗口大小
9. wmem_max — 发送窗口的最大大小
/proc目录下的所有内容都是临时性的, 所以重启动系统后任何修改都会丢失.
建议在系统启动时自动修改TCP/IP参数:
把下面代码增加到/etc/rc.local文件, 然后保存文件, 系统重新引导的时候会自动修改下面的TCP/IP参数:
echo 256960 > /proc/sys/net/core/rmem_default
echo 256960 > /proc/sys/net/core/rmem_max
echo 256960 > /proc/sys/net/core/wmem_default
echo 256960 > /proc/sys/net/core/wmem_max
echo 0 > /proc/sys/net/ipv4/tcp_timestamps
echo 1 > /proc/sys/net/ipv4/tcp_sack
echo 1 > /proc/sys/net/ipv4/tcp_window_scaling
TCP/IP参数都是自解释的, TCP窗口大小设置为256960, 禁止TCP的时间戳(取消在每个数据包的头中增加12字节), 支持更大的TCP窗口和TCP有选择的应答.
上面数值的设定是根据互连网连接和最大带宽/延迟率来决定.
注: 上面实例中的数值可以实际应用, 但它只包含了一部分参数.
另外一个方法: 使用 /etc/sysctl.conf 在系统启动时将参数配置成您所设置的值:
net.core.rmem_default = 256960
net.core.rmem_max = 256960
net.core.wmem_default = 256960
net.core.wmem_max = 256960
net.ipv4.tcp_timestamps = 0
net.ipv4.tcp_sack =1
net.ipv4.tcp_window_scaling = 1
调整 Linux 系统
本主题描述如何调整 Linux 操作系统以提高 WebSphere Application Server 的性能。
关于本任务
遇到性能问题时,请检查操作系统设置以确定这些设置是否适合于您的应用程序。由于 Linux 操作系统不是 WebSphere Application Server 产品,因此请注意,它可能会改变,并且结果可能会有所变化。
过程
根据调整需求,配置下列设置和变量:
  • timeout_timewait 参数
    • 描述:确定 TCP/IP 在释放已关闭的连接并再次使用其资源前必须经过的时间。关闭与释放之间的这段时间称为 TIME_WAIT 状态或者两倍最大段生存期(2MSL)状态。此时间期间,重新打开到客户机和服务器的连接的成本少于建立新连接。通过减少此条目的值,TCP/IP 可以更快地释放关闭的连接,并为新连接提供更多资源。如果正在运行的应用程序需要快速释放连接、创建新的连接,并且因为许多连接处于 TIME_WAIT 状态而导致低吞吐量,那么调整此参数。
    • 如何查看或设置: 发出以下命令,将 timeout_timewait 参数设置为 30 秒:
      echo 30 > /proc/sys/net/ipv4/tcp_fin_timeout
  • SUSE Linux Enterprise Server 8(SLES 8)SP2A - sched_yield_scale 调整
    • 描述:Linux 调度程序对上下文切换过度非常敏感,因此,已将修订包集成到 SLES 内核分发中,以便在线程发生处理时引入延迟。在 SLES 8 SP3 中将自动启用此修订包,但在 SLES 8 SP2A 或更高版本中,必须明确地启用它。
    • 如何查看或设置:
      1. 将 SLES 8 service pack 升级到 SP2A。
      2. 发出 sysctl -w sched_yield_scale=1 命令。
    • 缺省值:0
    • 建议值:1
  • RedHat Advanced Server 2.1 内核更新
    • 描述:RedHat Advanced Server 2.1 的内核更新已实现了影响 WebSphere Application Server 性能(尤其是内存到内存 HTTP 会话复制性能)的更改。
    • 如何查看或设置:
      1. 发出 uname -a 命令
      2. 如果正在运行 2.4.9-e.23 之前的任何内核,请至少升级到 RedHat Advanced Server 2.1 内核,最好升级到受支持的最新内核。
    • 缺省值:2.4.9-e.3
    • 建议值:2.4.9-e.23
  • Linux 文件描述符(ulimit)
    • 描述:指定支持打开的文件数。通常,缺省设置适合于大多数应用程序。如果将此参数值设置得太小,那么可能会显示文件打开错误、内存分配故障或连接建立错误。
    • 如何查看或设置:请参阅有关 ulimit 命令的 UNIX 参考页面以了解不同 shell 的语法。对于 KornShell shell(ksh)程序,要将 ulimit 命令设置为 8000,请发出 ulimit -n 8000 命令。使用 ulimit -a 命令来显示所有系统资源限制的当前值。
    • 缺省值:对于 SUSE Linux Enterprise Server 9(SLES 9),缺省值是 1024。
    • 建议值:8000
  • 连接储备
    • 描述:当由于入局连接请求比率过高而导致连接故障时,请更改下列参数: echo 3000 > /proc/sys/net/core/netdev_max_backlog
    • echo 3000 > /proc/sys/net/core/somaxconn
  • TCP_KEEPALIVE_INTERVAL
    • 描述:确定两次 isAlive 时间间隔探测之间的等待时间。
    • 如何查看或设置:发出以下命令来设置此值: echo 15 > /proc/sys/net/ipv4/tcp_keepalive_intvl
    • 缺省值:75 秒
    • 建议值:15 秒
  • TCP_KEEPALIVE_PROBES
    • 描述:确定超时前的探测次数。
    • 如何查看或设置:发出以下命令来设置此值: echo 5  > /proc/sys/net/ipv4/tcp_keepalive_probes
    • 缺省值:9 秒
    • 建议值:5 秒
To support over 500k users, you *need*
- A 64 bits hardware/kernel (AMD64, Opterons)
- At least 8GB of ram
- A recent linux kernel (2.6.x)
About tuning, I prefer to not fully disclose them because servers are targets of many attacks, so it's better not help hackers.
The most touchy thing is the IP route cache : You have to tune it or else the machine drops many connections
(hint : rhash_entries=... in the boot append string)
hints :
echo 1 > /proc/sys/net/ipv4/route/gc_interval
echo 150 >/proc/sys/net/ipv4/route/gc_timeout
echo 2 >/proc/sys/net/ipv4/route/gc_elasticity
- Use of hugeTLB pages
hint :
echo xxx >/proc/sys/vm/nr_hugepages
Tune tcp :
echo "4096 49152 131072" >/proc/sys/net/ipv4/tcp_wmem
echo xxxx >/proc/sys/net/ipv4/tcp_max_syn_backlog
echo xxxx >/proc/sys/net/core/somaxconn
echo 1200000 > /proc/sys/net/ipv4/tcp_max_tw_buckets
echo 7 >/proc/sys/net/ipv4/tcp_retries2
echo "600000 650000 700000" >/proc/sys/net/ipv4/tcp_mem
echo 0 >/proc/sys/net/ipv4/tcp_timestamps
echo 0 >/proc/sys/net/ipv4/tcp_window_scaling
echo 0 >/proc/sys/net/ipv4/tcp_sack
echo 330000 >/proc/sys/net/ipv4/tcp_max_orphans
echo "10000 62000" >/proc/sys/net/ipv4/ip_local_port_range
others :
echo 1300000 >/proc/sys/fs/file-max
为 Java 虚拟机(JVM)堆分配大页(针对 SLES 9 测试)
某些应用程序要求使用非常大的堆以提高性能。通过使用 CPU 和操作系统提供的“大页”支持,可以降低 CPU 管理大型堆的开销。以下示例假定大页大小为 4MB,并且期望的堆大小为 2300MB。
  1. 通过 sysctl.conf 文件(此文件通常是 /etc/sysctl.conf)设置下列三个设置。 注: 您必须具有 root 用户访问权才能修改此文件。并且,在尝试修改此文件前,请验证此文件是否是只读的。
    1. 通过发出以下命令,设置大页数(2300MB = 575 * 4MB): vm.nr_hugepages = 575
    2. 通过发出以下命令,将最大共享段大小设置为 2300MB 加上一个较小的增量(大约 95MB)(2511724800 = 2300MB * 1048576 字节/MB + 100000000 字节): kernel.shmmax = 2511724800
    3. 通过发出以下命令,设置要共享的总内存量:kernel.shmall = 2511724800
  2. 指定 -Xlp JVM 选项,以使 JVM 堆能够利用大页。
  3. 将 Xmx JVM 选项设置为 2300MB。
  4. 将程序文本重新定位到较低的虚拟内存地址(0x10000000)中,从而为较大的堆提供更多地址空间。在 SUSE Linux Enterprise Server 9 上,请运行以下命令来重新定位 JVM 调用脚本或 .profile 文件中的文本: echo "0x10000000" > /proc/self/mapped_base
结果
此调整过程提高了 Linux 操作系统上 WebSphere Application Server 的性能。
--------------------------

关于Linux内核参数的优化

net.ipv4.tcp_max_tw_buckets = 6000
timewait的数量,默认是180000。
net.ipv4.ip_local_port_range = 1024 65000
允许系统打开的端口范围。
net.ipv4.tcp_tw_recycle = 1
启用timewait快速回收。
net.ipv4.tcp_tw_reuse = 1
开启重用。允许将TIME-WAIT sockets重新用于新的TCP连接。
net.ipv4.tcp_syncookies = 1
开启SYN Cookies,当出现SYN等待队列溢出时,启用cookies来处理。
net.core.somaxconn = 262144
web应用中listen函数的backlog默认会给我们内核参数的net.core.somaxconn限制到128,而Nginx内核参数定义的NGX_LISTEN_BACKLOG默认为511,所以有必要调整这个值。
net.core.netdev_max_backlog = 262144
每个网络接口接收数据包的速率比内核处理这些包的速率快时,允许送到队列的数据包的最大数目。
net.ipv4.tcp_max_orphans = 262144
系统中最多有多少个TCP套接字不被关联到任何一个用户文件句柄上。如果超过这个数字,孤儿连接将即刻被复位并打印出警告信息。这个限制仅仅是为了防止简单的DoS攻击,不能过分依靠它或者人为地减小这个值,更应该增加这个值(如果增加了内存之后)。
net.ipv4.tcp_max_syn_backlog = 262144
记录的那些尚未收到客户端确认信息的连接请求的最大值。对于有128M内存的系统而言,缺省值是1024,小内存的系统则是128。
net.ipv4.tcp_timestamps = 0
时间戳可以避免序列号的卷绕。一个1Gbps的链路肯定会遇到以前用过的序列号。时间戳能够让内核接受这种“异常”的数据包。这里需要将其关掉。
net.ipv4.tcp_synack_retries = 1
为了打开对端的连接,内核需要发送一个SYN并附带一个回应前面一个SYN的ACK。也就是所谓三次握手中的第二次握手。这个设置决定了内核放弃连接之前发送SYN+ACK包的数量。
net.ipv4.tcp_syn_retries = 1
在内核放弃建立连接之前发送SYN包的数量。
net.ipv4.tcp_fin_timeout = 1
如 果套接字由本端要求关闭,这个参数决定了它保持在FIN-WAIT-2状态的时间。对端可以出错并永远不关闭连接,甚至意外当机。缺省值是60秒。 2.2 内核的通常值是180秒,你可以按这个设置,但要记住的是,即使你的机器是一个轻载的WEB服务器,也有因为大量的死套接字而内存溢出的风 险,FIN- WAIT-2的危险性比FIN-WAIT-1要小,因为它最多只能吃掉1.5K内存,但是它们的生存期长些。
net.ipv4.tcp_keepalive_time = 30
当keepalive起用的时候,TCP发送keepalive消息的频度。缺省是2小时.
-------------------------------

安装linux后的内核调优

安装linux后的内核调优
    kernel.shmall = 268435456
    net.ipv4.tcp_syncookies = 1
    net.ipv4.tcp_tw_reuse = 1
    net.ipv4.tcp_tw_recycle = 1
    net.ipv4.tcp_fin_timeout = 30
    net.ipv4.tcp_keepalive_time = 1200
    net.ipv4.ip_local_port_range = 1024 65000
    net.ipv4.tcp_max_tw_buckets = 5000
    net.ipv4.tcp_max_tw_buckets = 5000
    net.ipv4.tcp_fin_timeout = 30
    net.ipv4.tcp_keepalive_time = 300
    net.ipv4.tcp_syncookies = 1
    net.ipv4.tcp_tw_reuse = 1
    net.ipv4.tcp_tw_recycle = 1
    net.ipv4.ip_local_port_range = 5000 65000
    net.ipv4.tcp_mem = 786432 1048576 1572864
    net.core.wmem_max = 873200
    net.core.rmem_max = 873200
    net.ipv4.tcp_wmem = 8192 436600 873200
    net.ipv4.tcp_rmem = 32768 436600 873200
    net.core.somaxconn = 256
    net.core.netdev_max_backlog = 1000
    net.ipv4.tcp_max_syn_backlog = 2048
    net.ipv4.tcp_retries2 = 5
    net.ipv4.tcp_keepalive_time = 500
    net.ipv4.tcp_keepalive_intvl = 30
    net.ipv4.tcp_keepalive_probes = 3
    net.ipv4.conf.lo.arp_ignore = 0
    net.ipv4.conf.lo.arp_announce = 0
    net.ipv4.conf.all.arp_ignore = 0
    net.ipv4.conf.all.arp_announce = 0
  
 几个解释:
    net.ipv4.tcp_syncookies = 1
    #表示开启SYN Cookies。当出现SYN等待队列溢出时,启用cookies来处理,可防范少量SYN攻击,默认为0,表示关闭;
    net.ipv4.tcp_tw_reuse = 1
    #表示开启重用。允许将TIME-WAIT sockets重新用于新的TCP连接,默认为0,表示关闭;
    net.ipv4.tcp_tw_recycle = 1
    #表示开启TCP连接中TIME-WAIT sockets的快速回收,默认为0,表示关闭。
    net.ipv4.tcp_fin_timeout = 30
    #表示如果套接字由本端要求关闭,这个参数决定了它保持在FIN-WAIT-2状态的时间。
    net.ipv4.tcp_keepalive_time = 1200
    #表示当keepalive起用的时候,TCP发送keepalive消息的频度。缺省是2小时,改为20分钟。
    net.ipv4.ip_local_port_range = 1024    65000
    #表示用于向外连接的端口范围。缺省情况下很小:32768到61000,改为1024到65000。
    net.ipv4.tcp_max_tw_buckets = 5000
    #表示系统同时保持TIME_WAIT套接字的最大数量,如果超过这个数字,
    #TIME_WAIT套接字将立刻被清除并打印警告信息。默认为180000,改为5000。
    #对于Apache、Nginx等服务器,上几行的参数可以很好地减少TIME_WAIT套接字数量,
    #但是对于Squid,效果却不大。此项参数可以控制TIME_WAIT套接字的最大数量,避免Squid服务器被大量的TIME_WAIT套接字拖死。
---------------------------------------------
 
高流量,大并发的Linux TCP 性能调优
 

Linux Tuning

本文所面对的情况为:

  1. 高并发数
  2. 高延迟高丢包(典型的美国服务器)

值得注意的是,因为openvz的VPS权限比较低,能够修改的地方比较少,所以使用openvz的VPS作VPN服务器是非常不推荐的。

我们通过修改 /etc/sysctl.conf 来达到调整的目的,注意修改完以后记得使用:

sysctl -p

来使修改生效。

首先,针对高并发数,我们需要提高一些linux的默认限制:

fs.file-max = 51200
#提高整个系统的文件限制
net.ipv4.tcp_syncookies = 1
#表示开启SYN Cookies。当出现SYN等待队列溢出时,启用cookies来处理,可防范少量SYN攻击,默认为0,表示关闭;
net.ipv4.tcp_tw_reuse = 1
#表示开启重用。允许将TIME-WAIT sockets重新用于新的TCP连接,默认为0,表示关闭;
net.ipv4.tcp_tw_recycle = 0
#表示开启TCP连接中TIME-WAIT sockets的快速回收,默认为0,表示关闭;
#为了对NAT设备更友好,建议设置为0。
net.ipv4.tcp_fin_timeout = 30
#修改系統默认的 TIMEOUT 时间。
net.ipv4.tcp_keepalive_time = 1200
#表示当keepalive起用的时候,TCP发送keepalive消息的频度。缺省是2小时,改为20分钟。
net.ipv4.ip_local_port_range = 10000 65000 #表示用于向外连接的端口范围。缺省情况下很小:32768到61000,改为10000到65000。(注意:这里不要将最低值设的太低,否则可能会占用掉正常的端口!)
net.ipv4.tcp_max_syn_backlog = 8192
#表示SYN队列的长度,默认为1024,加大队列长度为8192,可以容纳更多等待连接的网络连接数。
net.ipv4.tcp_max_tw_buckets = 5000
#表示系统同时保持TIME_WAIT的最大数量,如果超过这个数字,TIME_WAIT将立刻被清除并打印警告信息。

#额外的,对于内核版本新于**3.7.1**的,我们可以开启tcp_fastopen:
net.ipv4.tcp_fastopen = 3

其次,针对大流量高丢包高延迟的情况,我们通过增大缓存来提高TCP性能,自己看E文注释吧……感觉我翻译出来各种味道不对 = =:

# increase TCP max buffer size settable using setsockopt()
net.core.rmem_max = 67108864 
net.core.wmem_max = 67108864 
# increase Linux autotuning TCP buffer limit
net.ipv4.tcp_rmem = 4096 87380 67108864
net.ipv4.tcp_wmem = 4096 65536 67108864
# increase the length of the processor input queue
net.core.netdev_max_backlog = 250000
# recommended for hosts with jumbo frames enabled
net.ipv4.tcp_mtu_probing=1

这里面涉及到一个TCP拥塞算法的问题,你可以用下面的命令查看本机提供的拥塞算法控制模块:

sysctl net.ipv4.tcp_available_congestion_control

如果没有下文提到的htcp,hybla算法,你可以尝试通过modprobe启用模块:

/sbin/modprobe tcp_htcp
/sbin/modprobe tcp_hybla

对于几种算法的分析,详情可以参考下:TCP拥塞控制算法 优缺点 适用环境 性能分析,但是这里面没有涉及到专门为卫星通讯设计的拥塞控制算法:Hybla。根据各位大神的实验,我们发现Hybla算法恰好是最适合美国服务器的TCP拥塞算法,而对于日本服务器,个人想当然的认为htcp算法应该可以比默认的cubic算法达到更好的效果。但是因为htcp算法恰好没有编入我们所使用的VPS中,所以没办法测试。

#设置TCP拥塞算法为 hybla
net.ipv4.tcp_congestion_control=hybla
更新:2014-06-22 修改TW快速回收的问题以更好的兼容移动设备。
----------------------------------------------------------------------
 
LINUX服务器的TCP调优

其实就是调整一下 sysctl.conf 文件,虽说这个其实应该算是经验得到的结果,但用起来确实有效,所以还是贴一下备忘吧。

net.ipv4.tcp_syncookies = 1
# 表示开启 SYN Cookies。当出现 SYN 等待队列溢出时,启用 cookies 来处理,可防范少量 SYN 攻击,默认为 0,表示关闭;
net.ipv4.tcp_tw_reuse = 1
# 表示开启重用。允许将 TIME-WAIT sockets 重新用于新的 TCP 连接,默认为 0,表示关闭;
net.ipv4.tcp_tw_recycle = 1
# 表示开启 TCP 连接中 TIME-WAIT sockets 的快速回收,默认为 0,表示关闭;
net.ipv4.tcp_fin_timeout = 30
# 修改系統默认的 TIMEOUT 时间。
net.ipv4.tcp_keepalive_time = 1200
# 表示当 keepalive 起用的时候,TCP 发送 keepalive 消息的频度。缺省是 2 小时,改为 20 分钟。
net.ipv4.ip_local_port_range = 10000 65000
# 表示用于向外连接的端口范围。缺省情况下很小:32768 到 61000,改为 10000 到 65000。(注意:这里不要将最低值设的太低,否则可能会占用掉正常的端口!)
net.ipv4.tcp_max_syn_backlog = 8192
# 表示 SYN 队列的长度,默认为 1024,加大队列长度为 8192,可以容纳更多等待连接的网络连接数。
net.ipv4.tcp_max_tw_buckets = 5000
# 表示系统同时保持 TIME_WAIT 的最大数量,如果超过这个数字,TIME_WAIT 将立刻被清除并打印警告信息。

# increase TCP max buffer size settable using setsockopt()
net.core.rmem_max = 67108864 
net.core.wmem_max = 67108864 
# increase Linux autotuning TCP buffer limit
net.ipv4.tcp_rmem = 4096 87380 67108864
net.ipv4.tcp_wmem = 4096 65536 67108864
# increase the length of the processor input queue
net.core.netdev_max_backlog = 250000
# recommended for hosts with jumbo frames enabled
net.ipv4.tcp_mtu_probing=1
# change the TCP congestion control algorithm
net.ipv4.tcp_congestion_control=hybla

在这里使用的是 Hybla 拥塞算法,感觉确实会比 Cubic 有改善。需要注意的是,这个更改前一般需要运行 modprobe tcp_hybla 一下。

---------------------------------------------

TCP拥塞控制算法 优缺点 适用环境 性能分析

 公平性


公平性是在发生拥塞时各源端(或同一源端建立的不同TCP连接或UDP数据报)能公平地共享同一网络资源(如带宽、缓存等)。处于相同级别的源端应该得到相同数量的网络资源。产生公平性的根本原因在于拥塞发生必然导致数据包丢失,而数据包丢失会导致各数据流之间为争抢有限的网络资源发生竞争,争抢能力弱的数据流将受到更多损害。因此,没有拥塞,也就没有公平性问题。

TCP层上的公平性问题表现在两方面:

(1) 面向连接的TCP和无连接的UDP在拥塞发生时对拥塞指示的不同反应和处理,导致对网络资源的不公平使用问题。在拥塞发生时,有拥塞控制反应机制的TCP数据流会按拥塞控制步骤进入拥塞避免阶段,从而主动减小发送入网络的数据量。但对无连接的数据报UDP,由于没有端到端的拥塞控制机制,即使网络发出了拥塞指示(如数据包丢失、收到重复ACK等),UDP也不会像TCP那样减少向网络发送的数据量。结果遵守拥塞控制的TCP数据流得到的网络资源越来越少,没有拥塞控制的UDP则会得到越来越多的网络资源,这就导致了网络资源在各源端分配的严重不公平。

网络资源分配的不公平反过来会加重拥塞,甚至可能导致拥塞崩溃。因此如何判断在拥塞发生时各个数据流是否严格遵守TCP拥塞控制,以及如何“惩罚”不遵守拥塞控制协议的行为,成了目前研究拥塞控制的一个热点。在传输层解决拥塞控制的公平性问题的根本方法是全面使用端到端的拥塞控制机制。

(2) 一些TCP连接之间也存在公平性问题。产生问题的原因在于一些TCP在拥塞前使用了大窗口尺寸,或者它们的RTT较小,或者数据包比其他TCP大,这样它们也会多占带宽。

 
RTT不公平性


AIMD拥塞窗口更新策略也存在一些缺陷,和式增加策略使发送方发送数据流的拥塞窗口在一个往返时延(RTT)内增加了一个数据包的大小,因此,当不同的数据流对网络瓶颈带宽进行竞争时,具有较小RTT的TCP数据流的拥塞窗口增加速率将会快于具有大RTT的TCP数据流,从而将会占有更多的网络带宽资源。

 

附加说明

中美之间的线路质量不是很好,rtt较长且时常丢包。TCP协议是成也丢包,败也丢包;TCP的设计目的是解决不可靠线路上可靠传输的问题,即为了解决丢包,但丢包却使TCP传输速度大幅下降。HTTP协议在传输层使用的是TCP协议,所以网页下载的速度就取决于TCP单线程下载的速度(因为网页就是单线程下载的)。
丢包使得TCP传输速度大幅下降的主要原因是丢包重传机制,控制这一机制的就是TCP拥塞控制算法。
Linux内核中提供了若干套TCP拥塞控制算法,已加载进内核的可以通过内核参数net.ipv4.tcp_available_congestion_control看到。

 
1. Vegas

1994年,Brakmo提出了一种新的拥塞控制机制TCP Vegas,从另外的一个角度来进行拥塞控制。从前面可以看到,TCP的拥塞控制是基于丢包的,一旦出现丢包,于是调整拥塞窗口,然而由于丢包不一定是由于网络进入了拥塞,但是由于RTT值与网络运行情况有比较密切的关系,于是TCP Vegas利用RTT值的改变来判断网络是否拥塞,从而调整拥塞控制窗口。如果发现RTT在增大,Vegas就认为网络正在发生拥塞,于是开始减小拥塞窗口,如果RTT变小,Vegas认为网络拥塞正在逐步解除,于是再次增加拥塞窗口。由于Vegas不是利用丢包来判断网络可用带宽,而是利用RTT变化来判断,因而可以更精确的探测网络的可用带宽,从而效率更好。然而Vegas的有一个缺陷,并且可以说致命的,最终影响TCP Vegas并没有在互联网上大规模使用。这个问题就是采用TCP Vegas的流的带宽竞争力不及未使用TCP Vegas的流,这是因为网络中路由器只要缓冲了数据,就会造成RTT的变大,如果缓冲区没有溢出的话,并不会发生拥塞,但是由于缓存数据就会导致处理时延,从而RTT变大,特别是在带宽比较小的网络上,只要一开始传输数据,RTT就会急剧增大,这个在无线网络上特别明显。在这种情况下,TCP Vegas降低自己的拥塞窗口,但是只要没有丢包的话,从上面看到标准的TCP是不会降低自己的窗口的,于是两者开始不公平,再这样循环下去,TCP Vegas的效率就非常低了。其实如果所有的TCP都采用Vegas拥塞控制方式的话,流之间的公平性会更好,竞争能力并不是Vegas算法本身的问题。

适用环境:很难在互联网上大规模适用(带宽竞争力低)

 
2. Reno

Reno是目前应用最广泛且较为成熟的算法。该算法所包含的慢启动、拥塞避免和快速重传、快速恢复机制,是现有的众多算法的基础。从Reno运行机制中很容易看出,为了维持一个动态平衡,必须周期性地产生一定量的丢失,再加上AIMD机制--减少快,增长慢,尤其是在大窗口环境下,由于一个数据报的丢失所带来的窗口缩小要花费很长的时间来恢复,这样,带宽利用率不可能很高且随着网络的链路带宽不断提升,这种弊端将越来越明显。公平性方面,根据统计数据,Reno的公平性还是得到了相当的肯定,它能够在较大的网络范围内理想地维持公平性原则。

Reno算法以其简单、有效和鲁棒性成为主流,被广泛的采用。

但是它不能有效的处理多个分组从同一个数据窗口丢失的情况。这一问题在New Reno算法中得到解决。

 
基于丢包反馈的协议

近几年来,随着高带宽延时网络(High Bandwidth-Delay product network)的普及,针对提高TCP带宽利用率这一点上,又涌现出许多新的基于丢包反馈的TCP协议改进,这其中包括HSTCP、STCP、BIC-TCP、CUBIC和H-TCP。

总的来说,基于丢包反馈的协议是一种被动式的拥塞控制机制,其依据网络中的丢包事件来做网络拥塞判断。即便网络中的负载很高时,只要没有产生拥塞丢包,协议就不会主动降低自己的发送速度。这种协议可以最大程度的利用网络剩余带宽,提高吞吐量。然而,由于基于丢包反馈协议在网络近饱和状态下所表现出来的侵略性,一方面大大提高了网络的带宽利用率;但另一方面,对于基于丢包反馈的拥塞控制协议来说,大大提高网络利用率同时意味着下一次拥塞丢包事件为期不远了,所以这些协议在提高网络带宽利用率的同时也间接加大了网络的丢包率,造成整个网络的抖动性加剧。


友好性


BIC-TCP、HSTCP、STCP等基于丢包反馈的协议在大大提高了自身吞吐率的同时,也严重影响了Reno流的吞吐率。基于丢包反馈的协议产生如此低劣的TCP友好性的组要原因在于这些协议算法本身的侵略性拥塞窗口管理机制,这些协议通常认为网络只要没有产生丢包就一定存在多余的带宽,从而不断提高自己的发送速率。其发送速率从时间的宏观角度上来看呈现出一种凹形的发展趋势,越接近网络带宽的峰值发送速率增长得越快。这不仅带来了大量拥塞丢包,同时也恶意吞并了网络中其它共存流的带宽资源,造成整个网络的公平性下降。

 
3. HSTCP(High Speed TCP)

HSTCP(高速传输控制协议)是高速网络中基于AIMD(加性增长和乘性减少)的一种新的拥塞控制算法,它能在高速度和大时延的网络中更有效地提高网络的吞吐率。它通过对标准TCP拥塞避免算法的增加和减少参数进行修改,从而实现了窗口的快速增长和慢速减少,使得窗口保持在一个足够大的范围,以充分利用带宽,它在高速网络中能够获得比TCP Reno高得多的带宽,但是它存在很严重的RTT不公平性。公平性指共享同一网络瓶颈的多个流之间占有的网络资源相等。

TCP发送端通过网络所期望的丢包率来动态调整HSTCP拥塞窗口的增量函数。

拥塞避免时的窗口增长方式: cwnd = cwnd + a(cwnd) / cwnd

丢包后窗口下降方式:cwnd = (1-b(cwnd))*cwnd

其中,a(cwnd)和b(cwnd)为两个函数,在标准TCP中,a(cwnd)=1,b(cwnd)=0.5,为了达到TCP的友好性,在窗口较低的情况下,也就是说在非BDP的网络环境下,HSTCP采用的是和标准TCP相同的a和b来保证两者之间的友好性。当窗口较大时(临界值LowWindow=38),采取新的a和b来达到高吞吐的要求。具体可以看RFC3649文档。

 
4. westwood

无线网络中,在大量研究的基础上发现tcpwestwood是一种较理想的算法,它的主要思想是通过在发送端持续不断的检测ack的到达速率来进行带宽估计,当拥塞发生时用带宽估计值来调整拥塞窗口和慢启动阈值,采用aiad(additive increase and adaptive decrease)拥塞控制机制。它不仅提高了无线网络的吞吐量,而且具有良好的公平性和与现行网络的互操作性。存在的问题是不能很好的区分传输过程中的拥塞丢包和无线丢包,导致拥塞机制频繁调用。

 
5. H-TCP

高性能网络中综合表现比较优秀的算法是:h-tcp,但它有rtt不公平性和低带宽不友好性等问题。

 
6. BIC-TCP

BIC-TCP的缺点:首先就是抢占性较强,BIC-TCP的增长函数在小链路带宽时延短的情况下比起标准的TCP来抢占性强,它在探测阶段相当于是重新启动一个慢启动算法,而TCP在处于稳定后窗口就是一直是线性增长的,不会再次执行慢启动的过程。其次,BIC-TCP的的窗口控制阶段分为binary search increase、max probing,然后还有Smax和Smin的区分,这几个值增加了算法上的实现难度,同时也对协议性能的分析模型增加了复杂度。在低RTT网络 和低速环境中,BIC可能会过于“积极”,因而人们对BIC进行了进一步的改进,即CUBIC。是Linux在采用CUBIC之前的默认算法。

 
7. CUBIC

CUBIC在设计上简化了BIC-TCP的窗口调整算法,在BIC-TCP的窗口调整中会出现一个凹和凸(这里的凹和凸指的是数学意义上的凹和凸,凹函数/凸函数)的增长曲线,CUBIC使用了一个三次函数(即一个立方函数),在三次函数曲线中同样存在一个凹和凸的部分,该曲线形状和BIC-TCP的曲线图十分相似,于是该部分取代BIC-TCP的增长曲线。另外,CUBIC中最关键的点在于它的窗口增长函数仅仅取决于连续的两次拥塞事件的时间间隔值,从而窗口增长完全独立于网络的时延RTT,之前讲述过的HSTCP存在严重的RTT不公平性,而CUBIC的RTT独立性质使得CUBIC能够在多条共享瓶颈链路的TCP连接之间保持良好的RTT公平性。

CUBIC is a congestion control protocol for TCP (transmission control protocol) and thecurrent default TCP algorithm in Linux. The protocol modifies the linear window growth function of existing TCP standards to be a cubic function in order to improve the scalability of TCP over fast and long distance networks. It also achieves more equitable bandwidth allocations among flows with different RTTs (round trip times) by making the window growth to be independent of RTT – thus those flows grow their congestion window at the same rate. During steady state, CUBIC increases the window size aggressively when the window is far from the saturation point, and the slowly when it is close to the saturation point.This feature allows CUBIC to be very scalable when the bandwidth and delay product of the network is large, and at the same time, be highly stable and also fair to standard TCP flows.

 
8. STCP

STCP,Scalable tcp。

STCP算法是由 Tom Kelly于 2003年提出的 ,通过修改 TCP的窗口增加和减少参数来调整发送窗口大小 ,以适应高速网络的环境。该算法具有很高的链路利用率和稳定性,但该机制窗口增加和 RTT成反比 ,在一定的程度上存在着 RTT不公平现象 ,而且和传统 TCP流共存时 ,过分占用带宽 ,其 TCP友好性也较差.

---------------

Linux Tuning

This page contains a quick reference guide for Linux tuning for Data Transfer hosts connected at speeds of 1Gbps or higher. Note that most of the tuning settings described here will actually decrease performance of hosts connected at rates less than 1Gbps, such as most home users on Cable/DSL connections.

Note that the settings on this page are not attempting to achieve full 10G with a single flow. These settings assume you are using tools that support parallel streams, or have multiple data transfers occurring in parallel, and want to have fair sharing between the flows.  As such the maximum values are 2 to 4 times less than what would be required to support a single stream.  As an example, a 10Gbps flow across a 100ms network requires 120MB of buffering (see the BDP calculator).  Most data movement applications, such as GridFTP, would employ 2-8 streams to do this efficiently and to guard against congestive packet loss.  Setting your 10Gbps capable host to consume a maximum of 32M - 64M per socket ensures that parallel streams work well, and do not consume a majority of system resources. 

If you are trying to optimize for a single flow, see the tuning advice for test / measurement hosts page.

 General Approach

To check what setting your system is using, use 'sysctl name' (e.g.: 'sysctl net.ipv4.tcp_rmem'). To change a setting use 'sysctl -w'. To make the setting permanent add the setting to the file 'sysctl.conf'.

 TCP tuning

Like most modern OSes, Linux now does a good job of auto-tuning the TCP buffers, but the default maximum Linux TCP buffer sizes are still too small. Here are some example sysctl.conf configurations for different types of hosts.

For a host with a 10G NIC, optimized for network paths up to 100ms RTT, and for friendliness to single and parallel stream tools, add this to /etc/sysctl.conf

# allow testing with buffers up to 64MB 
net.core.rmem_max = 67108864
net.core.wmem_max = 67108864
# increase Linux autotuning TCP buffer limit to 32MB
net.ipv4.tcp_rmem = 4096 87380 33554432
net.ipv4.tcp_wmem = 4096 65536 33554432
# recommended default congestion control is htcp
net.ipv4.tcp_congestion_control=htcp
# recommended for hosts with jumbo frames enabled
net.ipv4.tcp_mtu_probing=1
# recommended to enable 'fair queueing'
net.core.default_qdisc = fq

We also strongly recommend reducing the maximum flow rate to avoid bursts of packets that could overflow switch and receive host buffers.

For example for a 10G host, add this to a boot script:

    /sbin/tc qdisc add dev ethN root fq maxrate 8gbit 

For for a host running data transfer tools that use 4 parallel streams, do this:

    /sbin/tc qdisc add dev ethN root fq maxrate 2gbit 

 Where 'ethN' is the name of the ethernet device on your system.

For a host with a 10G NIC optimized for network paths up to 200ms RTT, and for friendliness to single and parallel stream tools, or a 40G NIC up on paths up to 50ms RTT:

# allow testing with buffers up to 128MB
net.core.rmem_max = 134217728
net.core.wmem_max = 134217728
# increase Linux autotuning TCP buffer limit to 64MB
net.ipv4.tcp_rmem = 4096 87380 67108864
net.ipv4.tcp_wmem = 4096 65536 67108864
# recommended default congestion control is htcp
net.ipv4.tcp_congestion_control=htcp
# recommended for hosts with jumbo frames enabled
net.ipv4.tcp_mtu_probing=1
# recommended to enable 'fair queueing'
net.core.default_qdisc = fq

Notes: you should leave net.tcp_mem alone, as the defaults are fine. A number of performance experts say to also increase net.core.optmem_max to match net.core.rmem_max and net.core.wmem_max, but we have not found that makes any difference. Some experts also say to set net.ipv4.tcp_timestamps and net.ipv4.tcp_sack to 0, as doing that reduces CPU load. We strongly disagree with that recommendation for WAN performance, as we have observed that the default value of 1 helps in more cases than it hurts, and can help a lot.

Linux supports pluggable congestion control algorithms. To get a list of congestion control algorithms that are available in your kernel (kernal  2.6.20+), run:

sysctl net.ipv4.tcp_available_congestion_control

cubic is usually the default in most linux distribution, but we have found htcp usually works better. You might also want to try BBR if its available on your system. 

To set the default congestion control algorithm, do:

sysctl -w net.ipv4.tcp_congestion_control=htcp

 

If you are using Jumbo Frames, we recommend setting tcp_mtu_probing = 1 to help avoid the problem of MTU black holes. Setting it to 2 sometimes causes performance problems.

from https://fasterdata.es.net/host-tuning/linux/