toc
问题: 两台服务器之间使用UDP通信,服务器A确认消息已发出,服务器B没有收到消息,请问有哪些可能?
这个问题如果直接去处理,可能会考虑框架日志、clb日志、k8s网卡日志等,反而把问题弄复杂了。其实可以理解为“丢包”问题,UDP丢包是非常常见的问题,由于协议本身就是非链接的传输协议,是不可靠的;所以准备从UDP协议原理出发,探讨下丢包的各种可能。
原理可以参考计算机网络(第7版)谢希仁.pdf
UDP是User Datagram Protocol的简称,中文名是用户数据报协议,是OSI参考模型中的传输层协议,它是一种**无连接的传输层协议**,提供面向事务的简单**不可靠**信息传送服务。
增大缓冲区
的方法来缓解UDP丢包问题。
注意
:如果服务已经过载
了,简单的增大缓冲区并不能解决问题,反而会造成滚雪球效应,造成请求全部超时
,服务不可用。int nReint nRecvBuf=32\*1024;//设置为32K
setsockopt(s,SOL\_SOCKET,SO\_RCVBUF,(constchar\*)&nRecvBuf,sizeof(int));
数据链路层地址解析协议APR(Address Resolution Protocol), 是根据IP地址获取物理地址的一个TCP/IP协议。主机发送信息时将包含目标IP地址的ARP请求广播到局域网络上的所有主机,并接收返回消息,以此确定目标的物理地址;收到返回消息后将该IP地址和物理地址存入本机ARP缓存中并保留一定时间,下次请求时直接查询ARP缓存以节约资源。
ARP 的缓存时间约 10 分钟,APR 缓存列表没有对方的 MAC 地址或缓存过期的时候,会发送 ARP 请求获取 MAC 地址,在没有获取到 MAC 地址之前,用户发送出去的 UDP 数据包会被内核缓存到 arp_queue 这个队列中,默认最多缓存 3 个包,多余的 UDP 包会被丢弃。
二次调用间隔
里,发过来的包可能丢失。对于这种情况可以修改接收端,数据接收与处理应当分离,将包接收后存入一个缓冲区,然后迅速返回继续 recv。
例如超过 50K 的一个 udp 包,不切割直接通过send 方法发送也会导致这个包丢失。
这种情况发送端需要切割成小包再逐个 send。以前在遇到过类似问题,日志上报常见,超长日志导致丢失。
由于UDP没有确认机制,没有流量控制和拥塞控制,这样在网络出现拥塞或通信两端处理能力不匹配的时候,UDP并不会进行调整发送速率,从而导致大量丢包。
发送端可以适当加入频率限制,适当sleep。
使用netstat命令,加-su参数。
bash-4.2# netstat -su
IcmpMsg:
InType3: 3
InType8: 2172282
InType11: 1
OutType0: 2172282
Udp:
2272520 packets received
0 packets to unknown port received.
0 packet receive errors
2272520 packets sent
`0 receive buffer errors`
0 send buffer errors
UdpLite:
IpExt:
InMcastPkts: 46285
InOctets: 8932526993
OutOctets: 7243339494
InMcastOctets: 1666260
InNoECTPkts: 54319536
每隔一段时间执行此命令,观察packet receive errors,如果不断变大则发生了丢包。
观察是否出现以下情况,如果是,可以先扩容,然后进行观察。
通过 cat /proc/sys/net/core/rmem_default 和cat /proc/sys/net/core/rmem_max可以查看socket缓冲区的缺省值和最大值。如果服务器的性能压力不大,对处理时延也没有很严格的要求,设置为1M左右即可。如果服务器的性能压力较大,或者对处理时延有很严格的要求,则必须谨慎设置rmem_default 和rmem_max,如果设得过小,会导致丢包,如果设得过大,会出现滚雪球。socket缓冲区设的过大导致滚雪球的问题,大家可以参考http://km.woa.com/user/bisonliao/articles/show/75674中的介绍,有定量的计算方法,分析得很深入。
UDP本身没有流量控制和拥塞控制,如果某些业务场景存在频繁发送的情况,可以适当增加延时发送逻辑。
如果排除了以上的原因,丢包率依旧较高,业务对可靠性要求较高,可以考虑以下方案。
TCP是面向连接的传输层协议,拥有流量控制、拥塞控制、有序的可靠传输协议。
缺点:相较于UDP,TCP的性能较差,连接成本高,速度慢。
KCP是一个快速可靠协议,能以比 TCP浪费10%-20%的带宽的代价,换取平均延迟降低 30%-40%,且最大延迟降低三倍的传输效果。纯算法实现,并不负责底层协议(如UDP)的收发,需要使用者自己定义下层数据包的发送方式,以 callback的方式提供给 KCP。 连时钟都需要外部传递进来,内部不会有任何一次系统调用。
QUIC(Quick UDP Internet Connection)是谷歌制定的一种基于UDP的低时延的互联网传输层协议。QUIC很好地解决了当今传输层和应用层面临的各种需求,包括处理更多的连接,安全性,和低延迟。QUIC融合了包括TCP,TLS,HTTP/2等协议的特性,但基于UDP传输。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。