浅谈UDP(数据包长度,收包能力,丢包及进程结构选择)

UDP数据包长度

UDP数据包的理论长度

udp数据包的理论长度是多少,合适的udp数据包应该是多少呢?从TCP-IP详解卷一第11章的udp数据包的包头可以看出,udp的最大包长度是2^16-1的个字节。由于udp包头占8个字节,而在ip层进行封装后的ip包头占去20字节,所以这个是udp数据包的最大理论长度是2^16-1-8-20=65507。

然而这个只是udp数据包的最大理论长度。首先,我们知道,TCP/IP通常被认为是一个四层协议系统,包括链路层、网络层、运输层、应用层。UDP属于运输层,在传输过程中,udp包的整体是作为下层协议的数据字段进行传输的,它的长度大小受到下层ip层和数据链路层协议的制约。

MTU相关概念

以太网(Ethernet)数据帧的长度必须在46-1500字节之间,这是由以太网的物理特性决定的。这个1500字节被称为链路层的MTU(最大传输单元)。因特网协议允许IP分片,这样就可以将数据包分成足够小的片段以通过那些最大传输单元小于该数据包原始大小的链路了。这一分片过程发生在网络层,它使用的是将分组发送到链路上的网络接口的最大传输单元的值。这个最大传输单元的值就是MTU(Maximum Transmission Unit)。它是指一种通信协议的某一层上面所能通过的最大数据包大小(以字节为单位)。最大传输单元这个参数通常与通信接口有关(网络接口卡、串口等)。

在因特网协议中,一条因特网传输路径的“路径最大传输单元”被定义为从源地址到目的地址所经过“路径”上的所有IP跳的最大传输单元的最小值。

需要注意的是,loopback的MTU不受上述限制,查看loopback MTU值:

[root@bogon ~]# cat /sys/class/net/lo/mtu

65536

IP分包udp数据包长度的影响

如上所述,由于网络接口卡的制约,mtu的长度被限制在1500字节,这个长度指的是链路层的数据区。对于大于这个数值的分组可能被分片,否则无法发送,而分组交换的网络是不可靠的,存在着丢包。IP 协议的发送方不做重传。接收方只有在收到全部的分片后才能 reassemble并送至上层协议处理代码,否则在应用程序看来这些分组已经被丢弃。

假定同一时刻网络丢包的概率是均等的,那么较大的IP datagram必然有更大的概率被丢弃,因为只要丢失了一个fragment,就导致整个IP datagram接收不到。不超过MTU的分组是不存在分片问题的。

MTU的值并不包括链路层的首部和尾部的18个字节。所以,这个1500字节就是网络层IP数据报的长度限制。因为IP数据报的首部为20字节,所以IP数据报的数据区长度最大为1480字节。而这个1480字节就是用来放TCP传来的TCP报文段或UDP传来的UDP数据报的。又因为UDP数据报的首部8字节,所以UDP数据报的数据区最大长度为1472字节。这个1472字节就是我们可以使用的字节数。

当我们发送的UDP数据大于1472的时候会怎样呢?这也就是说IP数据报大于1500字节,大于MTU。这个时候发送方IP层就需要分片(fragmentation)。把数据报分成若干片,使每一片都小于MTU。而接收方IP层则需要进行数据报的重组。而更严重的是,由于UDP的特性,当某一片数据传送中丢失时,接收方便无法重组数据报。将导致丢弃整个UDP数据报。因此,在普通的局域网环境下,将UDP的数据控制在1472字节以下为好。

进行Internet编程时则不同,因为Internet上的路由器可能会将MTU设为不同的值。如果我们假定MTU为1500来发送数据的,而途经的某个网络的MTU值小于1500字节,那么系统将会使用一系列的机制来调整MTU值,使数据报能够顺利到达目的地。鉴于Internet上的标准MTU值为576字节,所以在进行Internet的UDP编程时,最好将UDP的数据长度控件在548字节(576-8-20)以内。

UDP丢包

udp丢包是指网卡接收到数据包后,linux内核的tcp/ip协议栈在udp数据包处理过程中的丢包,主要原因有两个:

1、udp数据包格式错误或校验和检查失败。

2、应用程序来不及处理udp数据包。

对于原因1,udp数据包本身的错误很少见,应用程序也不可控,本文不讨论。

首先介绍通用的udp丢包检测方法,使用netstat命令,加-su参数。

# netstat -su

Udp:

2495354 packets received

2100876 packets to unknown port received.

3596307 packet receive errors

14412863 packets sent

RcvbufErrors: 3596307

SndbufErrors: 0

从上面的输出中,可以看到有一行输出包含了"packet receive errors",如果每隔一段时间执行netstat -su,发现行首的数字不断变大,表明发生了udp丢包。

下面介绍一下应用程序来不及处理而导致udp丢包的常见原因:

1、linux内核socket缓冲区设的太小 # cat /proc/sys/net/core/rmem_default

# cat /proc/sys/net/core/rmem_max

可以查看socket缓冲区的缺省值和最大值。

rmem_default和rmem_max设置为多大合适呢?如果服务器的性能压力不大,对处理时延也没有很严格的要求,设置为1M左右即可。如果服务器的性能压力较大,或者对处理时延有很严格的要求,则必须谨慎设置rmem_default 和rmem_max,如果设得过小,会导致丢包,如果设得过大,会出现滚雪球。

2、服务器负载过高,占用了大量cpu资源,无法及时处理linux内核socket缓冲区中的udp数据包,导致丢包。

一般来说,服务器负载过高有两个原因:收到的udp包过多;服务器进程存在性能瓶颈。如果收到的udp包过多,就要考虑扩容了。服务器进程存在性能瓶颈属于性能优化的范畴,这里不作过多讨论。

3、磁盘IO忙

服务器有大量IO操作,会导致进程阻塞,cpu都在等待磁盘IO,不能及时处理内核socket缓冲区中的udp数据包。如果业务本身就是IO密集型的,要考虑在架构上进行优化,合理使用缓存降低磁盘IO。

这里有一个容易忽视的问题:很多服务器都有在本地磁盘记录日志的功能,由于运维误操作导致日志记录的级别过高,或者某些错误突然大量出现,使得往磁盘写日志的IO请求量很大,磁盘IO忙,导致udp丢包。

对于运维误操作,可以加强运营环境的管理,防止出错。如果业务确实需要记录大量的日志,可以使用内存log或者远程log。

4、物理内存不够用,出现swap交换

swap交换本质上也是一种磁盘IO忙,因为比较特殊,容易被忽视,所以单列出来。

只要规划好物理内存的使用,并且合理设置系统参数,可以避免这个问题。

5)磁盘满导致无法IO

没有规划好磁盘的使用,监控不到位,导致磁盘被写满后服务器进程无法IO,处于阻塞状态。最根本的办法是规划好磁盘的使用,防止业务数据或日志文件把磁盘塞满,同时加强监控,例如开发一个通用的工具,当磁盘使用率达到80%时就持续告警,留出充足的反应时间。

UDP收包能力测试

测试环境

处理器:Intel(R) Xeon(R) CPU X3440 @ 2.53GHz,4核,8超线程,千兆以太网卡,8G内存

模型1

单机,单线程异步UDP服务,无业务逻辑,只有收包操作,除UDP包头外,一个字节数据。

测试结果

进程个数

1

2

4

8

平均处理速度(包/秒)

791676.1

1016197

1395040

1491744

网卡流量(Mb/s)

514.361

713.786

714.375

714.036

CPU占用情况(%)

100

200

325

370

现象:

1、单机UDP收包处理能力可以每秒达到150w左右。

2、处理能力随着进程个数的增加而增强。

3、在处理达到峰值时,CPU资源并未耗尽。

结论:

1、UDP的处理能力还是非常可观的。

2、对于现象2和现象3,可以看出,性能的瓶颈在网卡,而不在CPU,CPU的增加,处理能力的上升,来源于丢包(UDP_ERROR)个数的减少。

模型2

其他测试条件同模型1,除UDP包头外,一百个字节数据。

测试结果

进程个数

1

2

4

8

平均处理速度(包/秒)

571433.4

752319.9

731545.6

751922.5

网卡流量(Mb/s)

855.482

855.542

855.546

855.549

CPU占用情况(%)

100

112.9

——

——

现象:

1、100个字节的包大小,比较符合平常的业务情形。

2、UDP的处理能力还是非常可观,单机峰值可以到达每秒75w。

3、在4,8个进程时,没有记录CPU的占用情况(网卡流量耗尽),不过可以肯定的是,CPU未耗尽。

4、随着进程个数的上升,处理能力没有明显提升,但是,丢包(UDP_ERROR)的个数大幅下降。

模型3

单机,单进程,多线程异步UDP服务,多线程共用一个fd,无业务逻辑,除UDP包头外,一个字节数据。

测试结果:

线程个数

1

2

平均处理速度(包/秒)

791676

509868

网卡流量(Mb/s)

514.361

714.229

CPU占用情况(%)

100

150

现象:

1、随着线程个数的增加,处理能力不升反降。

结论:

1、多线程共用一个fd,会造成相当大的锁争用。

2、多线程共用一个fd,当有包来时,会激活所有的线程,导致频繁的上下文切换。

最终结论:

1、UDP处理能力非常可观,在日常的业务情形中,UDP一般不会成为性能瓶颈。

2、随着进程个数的增加,处理能力未明显上升,但是丢包个数明显下降。

3、本次测试过程中,瓶颈在网卡,而不在CPU。

4、采用多进程监听不同端口的模型,而不是多进程或多线程监听同一个端口。

总结

UDP数据包长度

在本机(loopback)传输,可以根据需要设置MTU,但记住,UDP最大理论长度65507。 在内网传输,最好控制在1472字节(1500-8-20)。 在internet上传输,最好控制在548字节(576-8-20)以内。

UDP收包能力

UDP处理能力非常可观,在日常的业务情形中,UDP一般不会成为性能瓶颈。 随着进程个数的增加,处理能力未明显上升,但是丢包个数明显下降。 采用多进程监听不同端口的模型,而不是多进程或多线程监听同一个端口。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏北京马哥教育

你真的掌握lvs工作原理吗?

lvs介绍 LVS(Linux Virtual Server 虚拟服务器):是一个虚拟的四层路由交换器集群系统,根据目标地址和目标端口实现用户请求转发。 lv...

63570
来自专栏开源优测

TCP/IP协议基础

TCP/IP 为网际协议族 IP或ICMP、TCP或UDP、TELNET或FTP、以及HTTP都属于TCP/IP

15510
来自专栏重庆的技术分享区

五(七)层互联网协议(计算机网络)深入浅出,看完必懂【图文一】

17550
来自专栏开源优测

RFC1180 TCP/IP指南

14620
来自专栏QQ音乐技术团队的专栏

Unity For Android Cardboard App ( 1 ):基础入门

本文针对的 VR 设备是 Cardboard,主要阐述的是如何在 Unity 环境下开发 VR 场景,实现视线与物体的简单交互。

35800
来自专栏Java3y

网络层【第一篇】

在当今我们是使用无连接的方式的。网络提供数据报服务,无连接的、尽最大努力交付的数据报服务。网络层不提供服务质量的承诺。即所传送的分组可能出错、丢失、重复和失序(...

19420
来自专栏SDNLAB

Mininet搭建多控制器拓扑

Mininet是一款非常轻巧但是功能很强大的网络模拟器。网络研究者可以使用Mininet创建支持OpenFlow的SDN拓扑。随着SDN研究的发展,多控制器协作...

57960
来自专栏彭湖湾的编程世界

【计算机网络】网络层学习笔记:总结IP,NAT和DHCP

前言:这篇文章是学习网络层协议时候总结的笔记,前面的主要部分介绍的都是IP协议, 后半部分介绍NAT协议和DHCP协议 参考书籍 《计算机网络-自顶向下》   ...

27250
来自专栏微信终端开发团队的专栏

微信终端跨平台组件 Mars 系列(三):连接超时与 IP & Port 排序

Mars 系列开始,将为大家介绍 STN(信令传输网络模块)。由于 STN 的复杂性,该模块将被分解为多个篇章进行介绍。本文主要介绍微信中关于 socket 连...

1.4K00
来自专栏即时通讯技术

网络编程懒人入门(一):快速理解网络通信协议(上篇)

论坛和群里常会有技术同行打算自已开发IM或者消息推送系统,很多时候连基本的网络编程理论(如网络协议等)都不了解,就贸然定方案、写代码,显得非常盲目且充满技术风险...

11110

扫码关注云+社区

领取腾讯云代金券