网络接收优化总结

144 阅读4分钟

Linux网络接收过程

Linux网络栈中,当数据帧到达网卡时,DMA控制器会将数据拷贝到内核缓冲区即RingBuffer环形队列中。DMA控制器拷贝完成会以硬中断通知CPU,CPU会调用网卡驱动注册的中断处理函数,进而发出软中断请求。之后ksoftirqd内核线程检测到软中断请求后,开始从RingBuffer循环收包并将包交给网络协议栈进行处理,处理完后会将最终数据放在用户进程的Socket接收队列中。

image.png

调整网卡RingBuffer大小

      RingBuffer就像是一个数据中转站,网卡将接收到的数据写入其中,内核ksoftirqd内核线程从中取走数据。如果某些时候,网卡瞬间来了很多数据,但ksoftirqd线程没处理过来,RingBuffer一直是满的状态,那后面来的数据就会被丢弃,为避免此种情况,可将RingBuffer调大一点:查看RingBuffer大小

[root@localhost ~]# ethtool -g enp0s3Ring parameters for enp0s3:Pre-set maximums:RX:             4096RX Mini:        n/aRX Jumbo:       n/aTX:             4096Current hardware settings:RX:             256RX Mini:        n/aRX Jumbo:       n/aTX:             256

可以看到enp0s3网卡最大支持4096,当前设置的是256,接下来我们调整为最大并查看

[root@localhost ~]# ethtool -G enp0s3 rx 4096 tx 4096[root@localhost ~]# ethtool -g enp0s3Ring parameters for enp0s3:Pre-set maximums:RX:             4096RX Mini:        n/aRX Jumbo:       n/aTX:             4096Current hardware settings:RX:             4096RX Mini:        n/aRX Jumbo:       n/aTX:             4096

为了确定是否因RingBuffer填满而导致丢包,我们可以通过如下命令来查看:

[root@localhost ~]# ethtool -S enp0s3 | grep rx_errors     rx_errors: 0

rx_errors大于0代表有包因RingBuffer装不下而被丢弃。

调优网卡多队列RSS

      当前主流网卡都支持多队列,此特性可以支持网卡创建多个RingBuffer队列。收到网络包后将包打散到多个队列中,而每个队列都有对应的CPU来进行处理,加大队列数可提高内核处理网络包的速度。查看网卡队列数目

ethtool -l enp0s3

设置网卡队列数目

ethtool -L enp0s3 combined 32

硬中断合并

      当DMA控制器将数据拷贝至系统内存后,就会通过硬中断通知CPU。如果数据包来得特别频繁,CPU就会频繁响应硬中断,在这方面造成一定损耗。那么为了提高CPU整体工作效率,可以对网卡硬中断进行合并,减少硬中断次数,以此达到目的。一般有如下三种策略供选择

Adaptive RX: on #自适应中断合并,网卡驱动自己判断合并时机
rx-usecs: 1 #一段时间后便会产生一个中断
rx-frames: 0 #累计接收这么多个帧后,产生一个中断

根据实际情况选择一种进行设置如下(一般选择自适应)

ethtool -C enp0s3 adaptive-rx on

软中断合并

      当ksoftirqd线程处理软中断时,会持续处理一批网络包后让出CPU以便其他线程运行。为了ksoftirqd可以多处理会儿网络包,我们可以调大其一次处理的网络包数量。查看ksoftirqd一次处理网络包的数目

sysctl -a | grep netdev_budgetnet.core.netdev_budget300

调大ksoftirqd一次处理网络包的数目(临时性,重启失效)

sysctl -w net.core.netdev_budget=1024

查看ksoftirqd一次处理网络包的数目(永久性)需写入/etc/sysctl.conf文件中

接收处理合并

      当我们在传输大文件时,多数包都是一段数据,都会经过网络协议栈,之后再进行合并,降低了CPU的效率。而LRO/GRO可以在包进行网络协议栈之前将多个小包合并成一个大包,这样提高了CPU使用效率。而两者的区别在于合并的地方不同,LRO在网卡中进行合并,GRO在内核源码中进行合并。可根据实际情况开启来提高CPU效率。查看是否打开了LRO/GRO

#ethtool -k enp0s3generic-receive-offload: off large-receive-offload: off

设置打开LRO/GRO

ethtool -K enp0s3 gro onethtool -K enp0s3 lro on

最后

同步更新至VX公众号:“后端技术专注者”,大家可以关注查看,谢谢!