Linux TCP队列相关参数的总结( 二 )

  • Mode 4 (802.3ad) IEEE 802.3ad动态链路聚合 。创建共享相同的速率和双工模式的聚合组
  • Mode 5 (balance-tlb) Adaptive transmit loadbalancing
  • Mode 6 (balance-alb) Adaptive loadbalancing
  • 2、网卡多队列及中断绑定
    随着网络的带宽的不断提升,单核CPU已经不能满足网卡的需求,这时通过多队列网卡驱动的支持,可以将每个队列通过中断绑定到不同的CPU核上,充分利用多核提升数据包的处理能力 。
    首先查看网卡是否支持多队列,使用lspci-vvv命令,找到Ethernetcontroller项:
    Linux TCP队列相关参数的总结

    文章插图
     
    如果有MSI-X,Enable+ 并且Count > 1,则该网卡是多队列网卡 。
    然后查看是否打开了网卡多队列 。使用命令cat/proc/interrupts,如果看到eth0-TxRx-0表明多队列支持已经打开:
    Linux TCP队列相关参数的总结

    文章插图
     
    最后确认每个队列是否绑定到不同的CPU 。cat/proc/interrupts查询到每个队列的中断号,对应的文件/proc/irq/${IRQ_NUM}/smp_affinity为中断号IRQ_NUM绑定的CPU核的情况 。以十六进制表示,每一位代表一个CPU核:
    (00000001)代表CPU0(00000010)代表CPU1(00000011)代表CPU0和CPU1
    如果绑定的不均衡,可以手工设置,例如:
    echo "1" > /proc/irq/99/smp_affinity echo "2" > /proc/irq/100/smp_affinity echo "4" > /proc/irq/101/smp_affinity echo "8" > /proc/irq/102/smp_affinity echo "10" > /proc/irq/103/smp_affinity echo "20" > /proc/irq/104/smp_affinity echo "40" > /proc/irq/105/smp_affinity echo "80" > /proc/irq/106/smp_affinity
    3、RingBuffer
    Ring Buffer位于NIC和IP层之间,是一个典型的FIFO(先进先出)环形队列 。RingBuffer没有包含数据本身,而是包含了指向sk_buff(socketkernel buffers)的描述符 。可以使用ethtool-g eth0查看当前RingBuffer的设置:
    Linux TCP队列相关参数的总结

    文章插图
     
    上面的例子接收队列为4096,传输队列为256 。可以通过ifconfig观察接收和传输队列的运行状况:
    Linux TCP队列相关参数的总结

    文章插图
     
    • RXerrors:收包总的错误数
    • RX dropped:表示数据包已经进入了RingBuffer,但是由于内存不够等系统原因,导致在拷贝到内存的过程中被丢弃 。
    • RX overruns:overruns意味着数据包没到RingBuffer就被网卡物理层给丢弃了,而CPU无法及时的处理中断是造成RingBuffer满的原因之一,例如中断分配的不均匀 。当dropped数量持续增加,建议增大RingBuffer,使用ethtool-G进行设置 。
    4、InputPacket Queue(数据包接收队列)
    当接收数据包的速率大于内核TCP处理包的速率,数据包将会缓冲在TCP层之前的队列中 。接收队列的长度由参数
    net.core.netdev_max_backlog设置 。
    5、recvBuffer
    recv buffer是调节TCP性能的关键参数 。BDP(Bandwidth-delayproduct,带宽延迟积) 是网络的带宽和与RTT(roundtrip time)的乘积,BDP的含义是任意时刻处于在途未确认的最大数据量 。RTT使用ping命令可以很容易的得到 。为了达到最大的吞吐量,recvBuffer的设置应该大于BDP,即recvBuffer >= bandwidth * RTT 。假设带宽是100Mbps,RTT是100ms,那么BDP的计算如下:
    BDP = 100Mbps * 100ms = (100 / 8) * (100 / 1000) = 1.25MB
    Linux在2.6.17以后增加了recvBuffer自动调节机制,recvbuffer的实际大小会自动在最小值和最大值之间浮动,以期找到性能和资源的平衡点,因此大多数情况下不建议将recvbuffer手工设置成固定值 。

    net.ipv4.tcp_moderate_rcvbuf设置为1时,自动调节机制生效,每个TCP连接的recvBuffer由下面的3元数组指定:
    net.ipv4.tcp_rmem =
    最初recvbuffer被设置为,同时这个缺省值会覆盖net.core.rmem_default的设置 。随后recvbuffer根据实际情况在最大值和最小值之间动态调节 。在缓冲的动态调优机制开启的情况下,我们将net.ipv4.tcp_rmem的最大值设置为BDP 。

    net.ipv4.tcp_moderate_rcvbuf被设置为0,或者设置了socket选项SO_RCVBUF,缓冲的动态调节机制被关闭 。recvbuffer的缺省值由net.core.rmem_default设置,但如果设置了net.ipv4.tcp_rmem,缺省值则被覆盖 。可以通过系统调用setsockopt()设置recvbuffer的最大值为net.core.rmem_max 。在缓冲动态调节机制关闭的情况下,建议把缓冲的缺省值设置为BDP 。
    注意这里还有一个细节,缓冲除了保存接收的数据本身,还需要一部分空间保存socket数据结构等额外信息 。因此上面讨论的recvbuffer最佳值仅仅等于BDP是不够的,还需要考虑保存socket等额外信息的开销 。Linux根据参数


    推荐阅读