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