随着网络的带宽的不断提升,单核CPU已经不能满足网卡的需求,这时通过多队列网卡驱动的支持,可以将每个队列通过中断绑定到不同的CPU核上,充分利用多核提升数据包的处理能力 。
首先查看网卡是否支持多队列,使用lspci-vvv命令,找到Ethernetcontroller项:

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

文章插图
最后确认每个队列是否绑定到不同的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的设置:

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

文章插图
- RXerrors:收包总的错误数
- RX dropped:表示数据包已经进入了RingBuffer,但是由于内存不够等系统原因,导致在拷贝到内存的过程中被丢弃 。
- RX overruns:overruns意味着数据包没到RingBuffer就被网卡物理层给丢弃了,而CPU无法及时的处理中断是造成RingBuffer满的原因之一,例如中断分配的不均匀 。当dropped数量持续增加,建议增大RingBuffer,使用ethtool-G进行设置 。
当接收数据包的速率大于内核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根据参数
推荐阅读
- Linux 环境下 DNS 域名解析服务
- Linux的系统启动卡制作及系统固化
- 通过十个问题助你彻底理解linux epoll工作原理
- 动图图解!既然IP层会分片,为什么TCP层也还要分段?
- linux内核协议栈 UDP之数据报接收过程
- Linux系统目录结构介绍
- Linux的sz和rz命令
- linux系统上查看载体为实体机还是虚拟机
- Linux上,最常用的十条命令
- Linux内核快速处理路径尽量多用kmem_cache而慎用kmalloc
