参考文章链接1:https://www.cnblogs.com/h2zZhou/p/12015409.html(侵权必删)
丢包检查方法
- 给每个UDP包编 ,对比收发端的接收到的包。对于UDP协议层上的包,例如RTP包,可以从RTP包中读出包的序列 进行判断。
- 抓包。发送端和接收端分别抓包。linux下可以使用tcpdump,windows下使用wireshark。
- linux下,可以使用watch netstat -su查看丢包统计。主要看RcvbufErrors和SndbufErrors。如果两个统计项的数字都在不断增加,表明 卡有丢包。
发送方丢包
发送的包太大
发送的包比64K大会导致UDP协议sendto返回错误。
发送的包比MTU大,UDP包在接收端容易丢包,可查看接收端的 卡统计。可考虑把包切分到MTU一下再发送。
发包速度太快
发包速度太快的话,可能有两个问题:1.接收端来不及接收导致接收端丢包。2.发送端 卡处理不过来。这个时候sendto没有返回错误,但是用netstat查看会发现SndbufErrors不断上升,有可能是 卡的输出队列太小导致。可以考虑使用ifconfig命令把txqueuelen设置大一些。
UDP包流量太大
同一个端口发送的数据量太大时会导致 卡丢包,这个时候可以用netstat查看会发现SndbufErrors不断上升。sendto会返回-1.这个时候可以考虑增大/proc/sys/net/core/wmem_max的值。
这种情况尤其是同时给多个客户端发送音视频数据时导致。笔者曾经遇到过这么一次情况。一个端口向8个客户端发送视频流时, 卡流量大概400M/s,sendto会返回-1,errno 11.程序里也调用setsockopt设置了发送缓冲区为60M,然而还是会丢包。后来将系统参数/proc/sys/net/core/wmem_max设到60M才解决问题。
接收端丢包
接收缓冲区太小
接收缓冲区小于发送客户端的包的大小,或者接收客户端recvfrom速度太慢,导致接收缓冲区满丢弃数据。前一种问题,可以考虑增大接收缓冲区。后一种问题,可以考虑将接收操作和业务处理操作分离到不同的线程来处理
参考文章链接2:https://www.cnblogs.com/lsgxeva/p/11124762.html(侵权必删)
解决方案:通过开启 卡多队列以及中断绑定来解决大流量下的 络丢包问题(暂时未测试)
1、判断当前系统环境是否支持多队列 卡,执行命令:
lspci -vvv
如果在Ethernet项中。含有MSI-X: Enable+ Count=9 Masked-语句,则说明当前系统环境是支持多队列 卡的,否则不支持。
2、ethtool -l eth0命令可以看到eth0 卡是否支持多队列,最多支持多少、当前开启多少
3、设置 卡当前使用多队列。运行命令:ethtool -L eth0 combined <N> N为要使能的队列数
4、要确保多队列确实生效,可以查看文件:
# ls /sys/class/net/eth0/queues/
rx-0 rx-2 rx-4 rx-6 tx-0 tx-2 tx-4 tx-6
rx-1 rx-3 rx-5 rx-7 tx-1 tx-3 tx-5 tx-7
如上,如果rx数量是设定值,则正确。
X86系统采用中断机制协同处理CPU与其他设备工作。长久以来 卡的中断默认由cpu0处理,在大量小包的 络环境下可能出现cpu0负载高,而其他cpu空闲。后来出现 卡多队列技术解决这个问题。
通过命令cat /proc/interrupts 查看系统中断信息,应该是长下面这个样子。第一列是中断 ,后面是每个cpu的中断数,可以通过grep过滤 卡来看相关的中断再那个CPU上执行
5、中断绑定
我们可以绑定中断 与处理CPU之间的关系,Linux系统用irqbalance服务优化中断分配,它能自动收集数据,调度中断请求。为了了解中断绑定,我们把irqbalance服务关掉,手工调整绑定关系。
/proc/irq/{IRQ_ID}/smp_affinity,中断IRQ_ID的CPU亲和配置文件,16进制
/proc/irq/{IRQ ID}/smp_affinity_list,10进制,与smp_affinity相通,修改一个相应改变。
[root@localhost ~]# cat /proc/interrupts | grep eth0
CPU0 CPU1 CPU2 CPU3 CPU4 CPU5 CPU6 CPU7
143: 0 0 0 0 1 0 0 0 IR-PCI-MSI-edge eth0
144: 68 67 58 297886391 69 57 68 59 IR-PCI-MSI-edge eth0-TxRx-0
145: 282217533 59 54 55 62 61 56 57 IR-PCI-MSI-edge eth0-TxRx-1
146: 52 269243896 51 46 55 50 53 54 IR-PCI-MSI-edge eth0-TxRx-2
147: 44 10 14 11 35 292342171 12 7 IR-PCI-MSI-edge eth0-TxRx-3[root@localhost ~]# cat /proc/irq/144/smp_affinity
08
[root@localhost ~]# cat /proc/irq/144/smp_affinity_list
3#上面表示的是08【00001000】,表示在cpu3上(从右往左,依次从CPU0~CPU7),和下面的3保持一致
[root@localhost ~]# echo 4 > /proc/irq/144/smp_affinity
修订后在进行压力测试,观察eth0的中断分压
RPS/RFS
RSS需要硬件支持,在不支持RSS的环境中,RPS/RFS提供了软件的解决方案。RPS(Receive Packet Steering)是把一个rx队列的软中断分发到多个CPU核上,从而达到负载均衡的目的。RFS(Receive Flow Steering)是RPS的扩展,RPS只依靠hash来控制数据包,提供负载平衡,但是没有考虑到应用程序的位置(指应用程序所在CPU)。RFS目标是通过指派应用线程正在运行的CPU处理中断,增加数据缓存的命中率。
参考文章链接3:https://cloud.tencent.com/developer/article/1638140
在开始之前,我们先用一张图解释 linux 系统接收 络 文的过程。
- 首先 络 文通过物理 线发送到 卡
- 络驱动程序会把 络中的 文读出来放到 ring buffer 中,这个过程使用 DMA(Direct Memory Access),不需要 CPU 参与
- 内核从 ring buffer 中读取 文进行处理,执行 IP 和 TCP/UDP 层的逻辑,最后把 文放到应用程序的 socket buffer 中
- 应用程序从 socket buffer 中读取 文进行处理
文章知识点与官方知识档案匹配,可进一步学习相关知识 络技能树首页概览22094 人正在系统学习中
声明:本站部分文章及图片源自用户投稿,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!