转自:https://blog.youkuaiyun.com/xingzheouc/article/details/49946191
1. UDP概念
用户数据报协议(英语:User Datagram Protocol,缩写为 UDP),又称使用者资料包协定,是一个简单的面向数据报的传输层协议,正式规范为RFC 768
在TCP/IP模型中,UDP为网络层以上和应用层以下提供了一个简单的接口。UDP只提供数据的不可靠传递,它一旦把应用程序发给网络层的数据发送出去,就不保留数据备份(所以UDP有时候也被认为是不可靠的数据报协议)。UDP在IP数据报的头部仅仅加入了复用和数据校验(字段)。
2. UDP丢包问题分析
由于UDP协议只提供数据的不可靠传输,数据包发出去后就不管了,数据包在网络的传输过程中都可能丢失。甚至即使数据包成功到达了接收端节点,也不意味着应用程序能够收到,因为要从网卡到达应用程序还需要经历很多阶段,每个阶段都可能丢包。
上图描述了一种应用程序接受网络数据包的典型路径图。
首先,NIC(网卡)接收和处理网络数据包。网卡有自己的硬件数据缓冲区,当网络数据流量太大,大到超过网卡的接收数据硬件缓冲区,这时新进入的数据包将覆盖之前缓冲区的数据包,导致丢失。网卡是否丢包取决于网卡本身的计算性能和硬件缓冲区的大小。
其次,网卡处理后把数据包交给操作系统缓冲区。数据包在操作系统阶段丢包主要取决于以下因素:
操作系统缓冲区的大小
系统的性能
系统的负载
网络相关的系统负载
最后,当数据包到达应用程序的socket缓冲区,如果应用程序不能及时从socket缓冲区把数据包取走,累积的数据包将会超出应用程序socket缓冲区阀值,导致缓冲区溢出,数据包丢失。数据包在应用程序阶段丢包主要取决于以下因素:
应用程序缓冲区大小
应用程序处理数据包的能力,即如何尽可能快的从缓冲区取走数据包
3. 针对UDP丢包问题,进行系统层面和程序层面调优
3.1 诊断
n 网卡缓冲区溢出诊断
在Linux操作系统中,可以通过netstat -i –udp 命令来诊断网卡缓冲区是否溢出,RX-DRP列显示网卡丢失的数据包个数。
For example: netstat -i –udp eth1
[root@TENCENT64 /usr/local/games/udpserver]# netstat -i –udp eth1
Kernel Interface table
Iface MTU Met RX-OK RX-ERR RX-DRPRX-OVR TX-OK TX-ERR TX-DRP TX-OVR Flg
eth1 1500012952182560307598497000BMRU
上图的输出显示3个数据包被网卡丢掉
可以通过增大网卡缓冲区来有效减少网卡缓冲区溢出。
n 操作系统内核网络缓冲区溢出诊断
在Linux操作系统中可以通过cat /proc/net/snmp | grep -w Udp命令来查看,InErrors 列显示当操作系统UDP队列溢出时丢失的UDP数据包总个数。
[root@TENCENT64 /usr/local/games/udpserver]# cat /proc/net/snmp | grep -w Udp
Udp: InDatagrams NoPorts InErrorsOutDatagrams RcvbufErrors SndbufErrors
Udp: 85942833112609927166563611 1514491665636110
有如下几种方法可以有效减缓操作系统缓冲区溢出:
1) 增大操作系统内核网络缓冲区的大小
2) 在数据包路径图中直接绕过操作系统内核缓冲区,通过使用用户空间栈或一些可以 绕过内核缓冲区的中间件 (e.g. Solarflare's OpenOnload).
3) 关闭未使用的网络相关的应用和服务使操作系统的负载降到最低
4) 系统中仅保留适当数量