UDP 通信过程中,丢包原因分析

    1. UDP buffer size 不足。linux 系统在接收报文之后,会把报文保存到缓存区中。因为缓存区的大小是有限的,如果出现 UDP 报文过大(超过缓存区大小或者 MTU 大小)、接收到报文的速率太快,都可能导致 linux 因为缓存满而直接丢包的情况。在系统层面,linux 设置了 receive buffer 可以配置的最大值。如果报文报文过大,可以在发送方对数据进行分割,保证每个报文的大小在 MTU 内。
    2. 系统负载过高。系统 CPU、memory、IO 负载过高都有可能导致网络丢包。如 CPU 如果负载过高,系统没有时间进行报文的 checksum 计算、复制内存等操作,从而导致网卡或者 socket buffer 出丢包;memory 负载过高,会应用程序处理过慢,无法及时处理报文;IO 负载过高,CPU 都用来响应 IO wait,没有时间处理缓存中的 UDP 报文。linux 系统本身就是相互关联的系统,任何一个组件出现问题都有可能影响到其他组件的正常运行。对于系统负载过高,要么是应用程序有问题,要么是系统不足。对于前者需要及时发现,debug 和修复;对于后者,也要及时发现并扩容。
    3. 应用丢包。上面提到系统的 UDP buffer size,调节的 sysctl 参数只是系统允许的最大值,每个应用程序在创建 socket 时需要设置自己 socket buffer size 的值。

    增加的 receive buffer 会减少丢包的可能性,但同时会导致应用使用更多的内存,需要谨慎使用。