精华内容
下载资源
问答
  • 最近工作中遇到某个服务器应用程序 UDP 丢包,在排查过程中查阅了很多资料,总结出来这篇文章,供更多人参考。 在开始之前,我们先用一张图解释 linux 系统接收网络报文的过程。 首先网络报文通过物理网线发送到...

    最近工作中遇到某个服务器应用程序 UDP 丢包,在排查过程中查阅了很多资料,总结出来这篇文章,供更多人参考。

    在开始之前,我们先用一张图解释 linux 系统接收网络报文的过程。

    1. 首先网络报文通过物理网线发送到网卡
    2. 网络驱动程序会把网络中的报文读出来放到 ring buffer 中,这个过程使用 DMA(Direct Memory Access),不需要 CPU 参与
    3. 内核从 ring buffer 中读取报文进行处理,执行 IP 和 TCP/UDP 层的逻辑,最后把报文放到应用程序的 socket buffer 中
    4. 应用程序从 socket buffer 中读取报文进行处理
      在这里插入图片描述
      在接收 UDP 报文的过程中,图中任何一个过程都可能会主动或者被动地把报文丢弃,因此丢包可能发生在网卡和驱动,也可能发生在系统和应用。

    之所以没有分析发送数据流程,一是因为发送流程和接收类似,只是方向相反;另外发送流程报文丢失的概率比接收小,只有在应用程序发送的报文速率大于内核和网卡处理速率时才会发生。

    本篇文章假定机器只有一个名字为 eth0 的 interface,如果有多个 interface 或者 interface 的名字不是 eth0,请按照实际情况进行分析。

    NOTE:
    文中出现的 RX(receive) 表示接收报文,TX(transmit) 表示发送报文。

    确认有 UDP 丢包发生
    要查看网卡是否有丢包,可以使用 ethtool -S eth0 查看,在输出中查找 bad 或者 drop 对应的字段是否有数据,在正常情况下,这些字段对应的数字应该都是 0。如果看到对应的数字在不断增长,就说明网卡有丢包。

    另外一个查看网卡丢包数据的命令是 ifconfig,它的输出中会有 RX(receive 接收报文)和 TX(transmit 发送报文)的统计数据:

    ~# ifconfig eth0
             RX packets 3553389376  bytes 2599862532475 (2.3 TiB)
            RX errors 0  dropped 1353  overruns 0  frame 0
            TX packets 3479495131  bytes 3205366800850 (2.9 TiB)
            TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
     
    

    此外,linux 系统也提供了各个网络协议的丢包信息,可以使用 netstat -s 命令查看,加上 --udp 可以只看 UDP 相关的报文数据:

    [root@holodesk02 GOD]# netstat -s -u
    IcmpMsg:
        InType0: 3
        InType3: 1719356
        InType8: 13
        InType11: 59
        OutType0: 13
        OutType3: 1737641
        OutType8: 10
        OutType11: 263
    Udp:
        517488890 packets received
        2487375 packets to unknown port received.
        47533568 packet receive errors
        147264581 packets sent
        12851135 receive buffer errors
        0 send buffer errors
    UdpLite:
    IpExt:
        OutMcastPkts: 696
        InBcastPkts: 2373968
        InOctets: 4954097451540
        OutOctets: 5538322535160
        OutMcastOctets: 79632
        InBcastOctets: 934783053
        InNoECTPkts: 5584838675
    

    对于上面的输出,关注下面的信息来查看 UDP 丢包的情况:

    • packet receive errors 不为空,并且在一直增长说明系统有 UDP 丢包
    • packets to unknown port received 表示系统接收到的 UDP 报文所在的目标端口没有应用在监听,一般是服务没有启动导致的,并不会造成严重的问题
    • receive buffer errors 表示因为 UDP 的接收缓存太小导致丢包的数

    NOTE: 并不是丢包数量不为零就有问题,对于 UDP 来说,如果有少量的丢包很可能是预期的行为,比如丢包率(丢包数量/接收报文数量)在万分之一甚至更低。

    网卡或者驱动丢包
    之前讲过,如果 ethtool -S eth0 中有 rx_***_errors 那么很可能是网卡有问题,导致系统丢包,需要联系服务器或者网卡供应商进行处理。

    # ethtool -S eth0 | grep rx_ | grep errors
         rx_crc_errors: 0
         rx_missed_errors: 0
         rx_long_length_errors: 0
         rx_short_length_errors: 0
         rx_align_errors: 0
         rx_errors: 0
         rx_length_errors: 0
         rx_over_errors: 0
         rx_frame_errors: 0
         rx_fifo_errors: 0
    

    netstat -i 也会提供每个网卡的接发报文以及丢包的情况,正常情况下输出中 error 或者 drop 应该为 0。

    如果硬件或者驱动没有问题,一般网卡丢包是因为设置的缓存区(ring buffer)太小,可以使用 ethtool 命令查看和设置网卡的 ring buffer。

    ethtool -g 可以查看某个网卡的 ring buffer,比如下面的例子

    # ethtool -g eth0
    Ring parameters for eth0:
    Pre-set maximums:
    RX:        4096
    RX Mini:    0
    RX Jumbo:    0
    TX:        4096
    Current hardware settings:
    RX:        256
    RX Mini:    0
    RX Jumbo:    0
    TX:        256
    

    Pre-set 表示网卡最大的 ring buffer 值,可以使用 ethtool -G eth0 rx 8192 设置它的值。

    Linux 系统丢包
    linux 系统丢包的原因很多,常见的有:UDP 报文错误、防火墙、UDP buffer size 不足、系统负载过高等,这里对这些丢包原因进行分析。

    UDP 报文错误
    如果在传输过程中UDP 报文被修改,会导致 checksum 错误,或者长度错误,linux 在接收到 UDP 报文时会对此进行校验,一旦发明错误会把报文丢弃。

    如果希望 UDP 报文 checksum 及时有错也要发送给应用程序,可以在通过 socket 参数禁用 UDP checksum 检查:

    int disable = 1;
    setsockopt(sock_fd, SOL_SOCKET, SO_NO_CHECK, (void*)&disable, sizeof(disable)
    

    防火墙
    如果系统防火墙丢包,表现的行为一般是所有的 UDP 报文都无法正常接收,当然不排除防火墙只 drop 一部分报文的可能性。

    如果遇到丢包比率非常大的情况,请先检查防火墙规则,保证防火墙没有主动 drop UDP 报文。

    UDP buffer size 不足
    linux 系统在接收报文之后,会把报文保存到缓存区中。因为缓存区的大小是有限的,如果出现 UDP 报文过大(超过缓存区大小或者 MTU 大小)、接收到报文的速率太快,都可能导致 linux 因为缓存满而直接丢包的情况。

    在系统层面,linux 设置了 receive buffer 可以配置的最大值,可以在下面的文件中查看,一般是 linux 在启动的时候会根据内存大小设置一个初始值。

    /proc/sys/net/core/rmem_max:允许设置的 receive buffer 最大值
    /proc/sys/net/core/rmem_default:默认使用的 receive buffer 值
    /proc/sys/net/core/wmem_max:允许设置的 send buffer 最大值
    /proc/sys/net/core/wmem_dafault:默认使用的 send buffer 最大值
    

    但是这些初始值并不是为了应对大流量的 UDP 报文,如果应用程序接收和发送 UDP 报文非常多,需要讲这个值调大。可以使用 sysctl 命令让它立即生效:

    sysctl -w net.core.rmem_max=26214400 # 设置为 25M
    

    也可以修改 /etc/sysctl.conf 中对应的参数在下次启动时让参数保持生效。

    如果报文报文过大,可以在发送方对数据进行分割,保证每个报文的大小在 MTU 内。

    另外一个可以配置的参数是 netdev_max_backlog,它表示 linux 内核从网卡驱动中读取报文后可以缓存的报文数量,默认是 1000,可以调大这个值,比如设置成 2000:

    sudo sysctl -w net.core.netdev_max_backlog=2000
    

    系统负载过高
    系统 CPU、memory、IO 负载过高都有可能导致网络丢包,比如 CPU 如果负载过高,系统没有时间进行报文的 checksum 计算、复制内存等操作,从而导致网卡或者 socket buffer 出丢包;memory 负载过高,会应用程序处理过慢,无法及时处理报文;IO 负载过高,CPU 都用来响应 IO wait,没有时间处理缓存中的 UDP 报文。

    linux 系统本身就是相互关联的系统,任何一个组件出现问题都有可能影响到其他组件的正常运行。对于系统负载过高,要么是应用程序有问题,要么是系统不足。对于前者需要及时发现,debug 和修复;对于后者,也要及时发现并扩容。

    应用丢包
    上面提到系统的 UDP buffer size,调节的 sysctl 参数只是系统允许的最大值,每个应用程序在创建 socket 时需要设置自己 socket buffer size 的值。

    linux 系统会把接受到的报文放到 socket 的 buffer 中,应用程序从 buffer 中不断地读取报文。所以这里有两个和应用有关的因素会影响是否会丢包:socket buffer size 大小以及应用程序读取报文的速度。

    对于第一个问题,可以在应用程序初始化 socket 的时候设置 socket receive buffer 的大小,比如下面的代码把 socket buffer 设置为 20MB:

    uint64_t receive_buf_size = 20*1024*1024;  //20 MB
    setsockopt(socket_fd, SOL_SOCKET, SO_RCVBUF, &receive_buf_size, sizeof(receive_buf_size));
    

    如果不是自己编写和维护的程序,修改应用代码是件不好甚至不太可能的事情。很多应用程序会提供配置参数来调节这个值,请参考对应的官方文档;如果没有可用的配置参数,只能给程序的开发者提 issue 了。

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

    另外一个因素是应用读取 buffer 中报文的速度,对于应用程序来说,处理报文应该采取异步的方式

    包丢在什么地方
    想要详细了解 linux 系统在执行哪个函数时丢包的话,可以使用 dropwatch 工具,它监听系统丢包信息,并打印出丢包发生的函数地址:

    # dropwatch -l kas
    Initalizing kallsyms db
    dropwatch> start
    Enabling monitoring...
    Kernel monitoring activated.
    Issue Ctrl-C to stop monitoring
    
    1 drops at tcp_v4_do_rcv+cd (0xffffffff81799bad)
    10 drops at tcp_v4_rcv+80 (0xffffffff8179a620)
    1 drops at sk_stream_kill_queues+57 (0xffffffff81729ca7)
    4 drops at unix_release_sock+20e (0xffffffff817dc94e)
    1 drops at igmp_rcv+e1 (0xffffffff817b4c41)
    1 drops at igmp_rcv+e1 (0xffffffff817b4c41)
    

    通过这些信息,找到对应的内核代码处,就能知道内核在哪个步骤中把报文丢弃,以及大致的丢包原因。

    此外,还可以使用 linux perf 工具监听 kfree_skb( 网络报文丢弃时会调用该函数) 事件的发生

    sudo perf record -g -a -e skb:kfree_skb
    sudo perf script
    

    关于 perf 命令的使用和解读,网上有很多文章可以参考。

    总结

    • UDP 本身就是无连接不可靠的协议,适用于报文偶尔丢失也不影响程序状态的场景,比如视频、音频、游戏、监控等。对报文可靠性要求比较高的应用不要使用 UDP,推荐直接使用 TCP。当然,也可以在应用层做重试、去重保证可靠性
    • 如果发现服务器丢包,首先通过监控查看系统负载是否过高,先想办法把负载降低再看丢包问题是否消失
    • 如果系统负载过高,UDP 丢包是没有有效解决方案的。如果是应用异常导致 CPU、memory、IO 过高,请及时定位异常应用并修复;如果是资源不够,监控应该能及时发现并快速扩容
    • 对于系统大量接收或者发送 UDP 报文的,可以通过调节系统和程序的 socket buffer size 来降低丢包的概率
    • 应用程序在处理 UDP 报文时,要采用异步方式,在两次接收报文之间不要有太多的处理逻辑
    展开全文
  • UDP丢包Linux)并测试

    千次阅读 2019-07-04 18:14:40
    一、UDP丢包现象 UDP丢包是正常现象,因为它是不安全的。 UDP是无连接的,面向消息的数据传输协议,与TCP相比,有两个致命的缺点,一是数据包容易丢失,二是数据包无序。 要实现文件的可靠传输,就必须在上层对...

    一、UDP丢包现象

    UDP丢包是正常现象,因为它是不安全的。

    UDP是无连接的,面向消息的数据传输协议,与TCP相比,有两个致命的缺点,一是数据包容易丢失,二是数据包无序。

    要实现文件的可靠传输,就必须在上层对数据丢包和乱序作特殊处理,必须要有要有丢包重发机制和超时机制。

    常见的可靠传输算法有模拟TCP协议,重发请求(ARQ)协议,它又可分为连续ARQ协议、选择重发ARQ协议、滑动窗口协议等等。

    1、我感觉原因可能有两个:

    (1)、客户端发送过快,网络状况不好或者超过服务器接收速度,就会丢包。

    (2)、原因是服务器收到包后,还要进行一些处理,而这段时间客户端发送的包没有去收,造成丢包。

    2、解决方法:

    (1)、客户端降低发送速度,可以等待回包,或者加一些延迟。

    (2)、服务器部分单独开一个线程,去接收UDP数据,存放在一个缓冲区中,又另外的线程去处理收到的数据,尽量减少因为处理数据延时造成的丢包。

    3、总结:

    如果必须使用UDP,而且丢包又是不能接受的,只好自己实现确认和重传,说白了,就是自己实现TCP(当然是部分和有限的简单实现)。

    二、如何制造UDP丢包?

    如果只是小规模程序,也可以自己实现丢包处理,原理基本上就是给文件分块,每个数据包的头部添加一个唯一标识序号的ID值,当接收的包头部ID不是期望中的ID号,则判定丢包,将丢包ID发回服务端,服务器端接到丢包响应则重发丢失的数据包。

    UDP是面向无连接的,用户在实施UDP编程时,必须制定上层的协议,包括流控制,简单的超时和重传机制,如果不要求是实时数据,我想TCP可能会更适合你!

    三、怎样测试UDP并发性能?

    1、连续把程序跑24个小时。

    2、一般就是在同一个时间段内采用大量的客户端或者一个客户端采用多线程的方式向服务器发送数据,因此也就是多线程或者多进程的的方式来模拟发送数据的形式

    展开全文
  • https://cizixs.com/2018/01/13/linux-udp-packet-drop-debug/本文链接最近工作中遇到某个服务器应用程序 UDP 丢包,在排查过程中查...

    https://cizixs.com/2018/01/13/linux-udp-packet-drop-debug/

    本文链接


    最近工作中遇到某个服务器应用程序 UDP 丢包,在排查过程中查阅了很多资料,我在排查过程中基本都是通过使用 tcpdump 在出现问题的各个环节上进行抓包、分析在那个环节出现问题、针对性去排查解决问题,对症下药,最后终究能够解决问题。但是这种情况大多是因为服务本身的问题,如果是环境问题、操作系统、甚至硬件的问题,可能从服务本身出发不能解决问题,但是这篇文章另辟蹊径,从外部环境分析可能丢包的原因,看完之后,很受用,部分章节对原文有所修改,下面分享出来供更多人参考。


    在开始之前,我们先用一张图解释 linux 系统接收网络报文的过程。

    1. 首先网络报文通过物理网线发送到网卡

    2. 网络驱动程序会把网络中的报文读出来放到 ring buffer 中,这个过程使用 DMA(Direct Memory Access),不需要 CPU 参与

    3. 内核从 ring buffer 中读取报文进行处理,执行 IP 和 TCP/UDP 层的逻辑,最后把报文放到应用程序的 socket buffer 中

    4. 应用程序从 socket buffer 中读取报文进行处理


    在接收 UDP 报文的过程中,图中任何一个过程都可能会主动或者被动地把报文丢弃,因此丢包可能发生在网卡和驱动,也可能发生在系统和应用。

    之所以没有分析发送数据流程,一是因为发送流程和接收类似,只是方向相反;另外发送流程报文丢失的概率比接收小,只有在应用程序发送的报文速率大于内核和网卡处理速率时才会发生。

    本篇文章假定机器只有一个名字为 eth0 的 interface,如果有多个 interface 或者 interface 的名字不是 eth0,请按照实际情况进行分析。

    NOTE:文中出现的 RX(receive) 表示接收报文,TX(transmit) 表示发送报文。

    确认有 UDP 丢包发生

    要查看网卡是否有丢包,可以使用 ethtool -S eth0 查看,在输出中查找 bad 或者 drop 对应的字段是否有数据,在正常情况下,这些字段对应的数字应该都是 0。如果看到对应的数字在不断增长,就说明网卡有丢包。

    另外一个查看网卡丢包数据的命令是 ifconfig,它的输出中会有 RX(receive 接收报文)和 TX(transmit 发送报文)的统计数据:

    [root@k8s-master ng]# ifconfig enp1
    enp2s0f1: flags=4099<UP,BROADCAST,MULTICAST>  mtu 1500
            ether 04:b0:e7:fa:75:9d  txqueuelen 1000  (Ethernet)
            RX packets 0  bytes 0 (0.0 B)
            RX errors 0  dropped 0  overruns 0  frame 0
            TX packets 0  bytes 0 (0.0 B)
            TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
            device memory 0x92200000-922fffff
    

    此外,linux 系统也提供了各个网络协议的丢包信息,可以使用 netstat -s 命令查看,加上 --udp 可以只看 UDP 相关的报文数据:

    [root@k8s-master ng]# netstat -s -u
    IcmpMsg:
        InType0: 17
        InType3: 75
        InType8: 77
        OutType0: 77
        OutType3: 692
        OutType8: 249
    Udp:
        5728807 packets received
        12 packets to unknown port received.
        0 packet receive errors
        982710 packets sent
        0 receive buffer errors
        0 send buffer errors
    UdpLite:
    IpExt:
        InNoRoutes: 3
        InBcastPkts: 497633
        InOctets: 1044710406807
        OutOctets: 17460621991142
        InBcastOctets: 114600482
        InNoECTPkts: 2886955071
    
    
    

    对于上面的输出,关注下面的信息来查看 UDP 丢包的情况:

    • packet receive errors 不为空,并且在一直增长说明系统有 UDP 丢包

    • packets to unknown port received 表示系统接收到的 UDP 报文所在的目标端口没有应用在监听,一般是服务没有启动导致的,并不会造成严重的问题

    • receive buffer errors 表示因为 UDP 的接收缓存太小导致丢包的数量

    NOTE:并不是丢包数量不为零就有问题,对于 UDP 来说,如果有少量的丢包很可能是预期的行为,比如丢包率(丢包数量/接收报文数量)在万分之一甚至更低。

    网卡或者驱动丢包

    之前讲过,如果 ethtool -S eth0 中有 rx_***_errors 那么很可能是网卡有问题,导致系统丢包,需要联系服务器或者网卡供应商进行处理。

    [root@k8s-master ng]# ethtool -S enp1 | grep rx_ | grep errors
         rx_crc_errors: 0
         rx_missed_errors: 0
         rx_long_length_errors: 0
         rx_short_length_errors: 0
         rx_align_errors: 0
         rx_errors: 0
         rx_length_errors: 0
         rx_over_errors: 0
         rx_frame_errors: 0
         rx_fifo_errors: 0
    
    
    

    netstat -i 也会提供每个网卡的接发报文以及丢包的情况,正常情况下输出中 error 或者 drop 应该为 0。

    如果硬件或者驱动没有问题,一般网卡丢包是因为设置的缓存区(ring buffer)太小,可以使用 ethtool 命令查看和设置网卡的 ring buffer。

    ethtool -g 可以查看某个网卡的 ring buffer,比如下面的例子

    [root@k8s-master ng]# ethtool -g enp1
    Ring parameters for enp2s0f1:
    Pre-set maximums:
    RX:    4096
    RX Mini:  0
    RX Jumbo:  0
    TX:    4096
    Current hardware settings:
    RX:    256
    RX Mini:  0
    RX Jumbo:  0
    TX:    256
    
    
    

    Pre-set 表示网卡最大的 ring buffer 值,可以使用 ethtool -G eth0 rx 8192 设置它的值。

    Linux 系统丢包

    linux 系统丢包的原因很多,常见的有:UDP 报文错误、防火墙、UDP buffer size 不足、系统负载过高等,这里对这些丢包原因进行分析。

    UDP 报文错误

    如果在传输过程中UDP 报文被修改,会导致 checksum 错误,或者长度错误,linux 在接收到 UDP 报文时会对此进行校验,一旦发明错误会把报文丢弃。

    如果希望 UDP 报文 checksum 及时有错也要发送给应用程序,可以在通过 socket 参数禁用 UDP checksum 检查。

    防火墙

    如果系统防火墙丢包,表现的行为一般是所有的 UDP 报文都无法正常接收,当然不排除防火墙只 drop 一部分报文的可能性。

    如果遇到丢包比率非常大的情况,请先检查防火墙规则,保证防火墙没有主动 drop UDP 报文。

    UDP buffer size 不足

    linux 系统在接收报文之后,会把报文保存到缓存区中。因为缓存区的大小是有限的,如果出现 UDP 报文过大(超过缓存区大小或者 MTU 大小)、接收到报文的速率太快,都可能导致 linux 因为缓存满而直接丢包的情况。

    在系统层面,linux 设置了 receive buffer 可以配置的最大值,可以在下面的文件中查看,一般是 linux 在启动的时候会根据内存大小设置一个初始值。

    • /proc/sys/net/core/rmem_max:允许设置的 receive buffer 最大值

    • /proc/sys/net/core/rmem_default:默认使用的 receive buffer 值

    • /proc/sys/net/core/wmem_max:允许设置的 send buffer 最大值

    • /proc/sys/net/core/wmem_dafault:默认使用的 send buffer 最大值

    但是这些初始值并不是为了应对大流量的 UDP 报文,如果应用程序接收和发送 UDP 报文非常多,需要讲这个值调大。可以使用 sysctl 命令让它立即生效:

    [root@k8s-master ~]# sysctl -w net.core.rmem_max=26214400 # 设置为 25M
    net.core.rmem_max = 26214400
    

    也可以修改 /etc/sysctl.conf 中对应的参数在下次启动时让参数保持生效。

    如果报文报文过大,可以在发送方对数据进行分割,保证每个报文的大小在 MTU 内。

    另外一个可以配置的参数是 netdev_max_backlog,它表示 linux 内核从网卡驱动中读取报文后可以缓存的报文数量,默认是 1000,可以调大这个值,比如设置成 2000:

    [root@k8s-master ~]# sudo sysctl -w net.core.netdev_max_backlog=2000
    net.core.netdev_max_backlog = 2000
    [root@k8s-master ~]#
    

    系统负载过高

    系统 CPU、memory、IO 负载过高都有可能导致网络丢包,比如 CPU 如果负载过高,系统没有时间进行报文的 checksum 计算、复制内存等操作,从而导致网卡或者 socket buffer 出丢包;memory 负载过高,会应用程序处理过慢,无法及时处理报文;IO 负载过高,CPU 都用来响应 IO wait,没有时间处理缓存中的 UDP 报文。

    linux 系统本身就是相互关联的系统,任何一个组件出现问题都有可能影响到其他组件的正常运行。对于系统负载过高,要么是应用程序有问题,要么是系统不足。对于前者需要及时发现,debug 和修复;对于后者,也要及时发现并扩容。

    应用丢包

    上面提到系统的 UDP buffer size,调节的 sysctl 参数只是系统允许的最大值,每个应用程序在创建 socket 时需要设置自己 socket buffer size 的值。

    linux 系统会把接受到的报文放到 socket 的 buffer 中,应用程序从 buffer 中不断地读取报文。所以这里有两个和应用有关的因素会影响是否会丢包:socket buffer size 大小以及应用程序读取报文的速度。

    对于第一个问题,可以在应用程序初始化 socket 的时候设置 socket receive buffer 的大小,比如下面的代码把 socket buffer 设置为 20MB:

    uint64_t receive_buf_size = 20*1024*1024;  //20 MB
    setsockopt(socket_fd, SOL_SOCKET, SO_RCVBUF, &receive_buf_size, sizeof(receive_buf_size));
    

    如果不是自己编写和维护的程序,修改应用代码是件不好甚至不太可能的事情。很多应用程序会提供配置参数来调节这个值,请参考对应的官方文档;如果没有可用的配置参数,只能给程序的开发者提 issue 了。

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

    另外一个因素是应用读取 buffer 中报文的速度,对于应用程序来说,处理报文应该采取异步的方式

    包丢在什么地方

    想要详细了解 linux 系统在执行哪个函数时丢包的话,可以使用 dropwatch 工具,它监听系统丢包信息,并打印出丢包发生的函数地址:

    # dropwatch -l kas
    Initalizing kallsyms db
    dropwatch> start
    Enabling monitoring...
    Kernel monitoring activated.
    Issue Ctrl-C to stop monitoring
    
    
    1 drops at tcp_v4_do_rcv+cd (0xffffffff81799bad)
    10 drops at tcp_v4_rcv+80 (0xffffffff8179a620)
    1 drops at sk_stream_kill_queues+57 (0xffffffff81729ca7)
    4 drops at unix_release_sock+20e (0xffffffff817dc94e)
    1 drops at igmp_rcv+e1 (0xffffffff817b4c41)
    1 drops at igmp_rcv+e1 (0xffffffff817b4c41)
    

    通过这些信息,找到对应的内核代码处,就能知道内核在哪个步骤中把报文丢弃,以及大致的丢包原因。本人在排查这个问题过程中更倾向于在各个机器抓包,这个方法更适合追踪自身业务出现问题导致丢包,如下所示:

    tcpdump -i 网络接口名称 udp port 2020 -s0 -XX -nn
    

    此外,还可以使用 linux perf 工具监听 kfree_skb(把网络报文丢弃时会调用该函数) 事件的发生:

    sudo perf record -g -a -e skb:kfree_skb
    sudo perf script
    
    
    

    关于 perf 命令的使用和解读,网上有很多文章可以参考。


    总结

    • UDP 本身就是无连接不可靠的协议,适用于报文偶尔丢失也不影响程序状态的场景,比如视频、音频、游戏、监控等。对报文可靠性要求比较高的应用不要使用 UDP,推荐直接使用 TCP。当然,也可以在应用层做重试、去重保证可靠性

    • 如果发现服务器丢包,首先通过监控查看系统负载是否过高,先想办法把负载降低再看丢包问题是否消失

    • 如果系统负载过高,UDP 丢包是没有有效解决方案的。如果是应用异常导致 CPU、memory、IO 过高,请及时定位异常应用并修复;如果是资源不够,监控应该能及时发现并快速扩容

    • 对于系统大量接收或者发送 UDP 报文的,可以通过调节系统和程序的 socket buffer size 来降低丢包的概率

    • 应用程序在处理 UDP 报文时,要采用异步方式,在两次接收报文之间不要有太多的处理逻辑

    推荐:


    基础知识普及-网络抓包工具(tcpdump)

    TCP滑动窗口消息堆积


    随手关注或者”在看“,诚挚感谢!

    展开全文
  • Linuxudp丢包分析

    2020-06-18 17:17:43
    分析udp丢包,需要分析带序号的报文,RTP报文,可以分析丢包情况;若是分析iperf的udp包,没法分析出丢包来。 网上说可以使用watch netstat -su查看丢包统计。主要看RcvbufErrors和SndbufErrors,packet receive ...

    wireshark分析tcp的丢包比较简单,因为可以分析重发次数,和响应;
    分析udp的丢包,需要分析带序号的报文,RTP报文,可以分析丢包情况;若是分析iperf的udp包,没法分析出丢包来。

    网上说可以使用watch netstat -su查看丢包统计。主要看RcvbufErrors和SndbufErrors,packet receive errors。
    丢包原因:
    发送端:1. 发送的包太大,2.发包速度太快,3.udp包流量太大,发送缓冲区又太小。
    接收端:接收缓冲区太小


    使用 sysctl -a | grep memsocket查看缓冲区大小

    lmz@X280:~/下载$ sudo sysctl -a | grep mem
    [sudo] lmz 的密码: 
    net.core.optmem_max = 20480
    net.core.rmem_default = 212992
    net.core.rmem_max = 212992
    net.core.wmem_default = 212992
    net.core.wmem_max = 212992
    net.ipv4.fib_sync_mem = 524288
    net.ipv4.igmp_max_memberships = 20
    net.ipv4.tcp_mem = 92376	123168	184752
    net.ipv4.tcp_rmem = 4096	131072	6291456
    net.ipv4.tcp_wmem = 4096	16384	4194304
    net.ipv4.udp_mem = 184752	246336	369504
    net.ipv4.udp_rmem_min = 4096
    net.ipv4.udp_wmem_min = 4096
    vm.lowmem_reserve_ratio = 256	256	32	0	0
    vm.memory_failure_early_kill = 0
    vm.memory_failure_recovery = 1
    vm.nr_hugepages_mempolicy = 0
    vm.overcommit_memory = 0
    

    /etc/sysctl.conf 修改rmem_default、rmem_max、wmem_default和wmem_max的值,执行sysctl -p即可生效。

    展开全文
  • 测试系统在Linux上的性能发现丢包率极为严重,发210000条数据,丢包达110000之巨,丢包率超过50%。同等情形下Windows上测试,仅丢几条数据。形势严峻,必须解决。考虑可能是因为协议栈Buffer太低所致,于是先看看...
  • 最近工作中遇到某个服务器应用程序 UDP 丢包,在排查过程中查阅了很多资料,我在排查过程中基本都是通过使用 tcpdump 在出现问题的各个环节上进行抓包、分析在那个环节出现问题、针对性去排查解决问题,对症下药,...
  • 大神们好,小弟最近做了一个LINUX网卡驱动,用iperf来测试时候,发现UDP丢包。 用iperf测试UDP,一共测试两次,一次一个小时,速率为1000M,丢包率大概在0.0001%左右 再继续测试时,发现会大量丢包,已经惨不忍睹...
  • udp丢包原因分析

    2020-01-06 11:15:20
    什么会导致udp丢包呢,这里列举了如下几点原因: 调用recv方法接收端收到数据后,处理数据花了一些时间,处理完后再次调用recv方法,在这二次调用间隔里,发过来的包可能丢失。对于这种情况可以修改接收端,将包...
  • 丢包检查方法 给每个UDP包编号,对比收发端的接收到的包。对于UDP协议层上的包,例如RTP包,可以从RTP包中读出包的... linux下,可以使用watch netstat -su查看丢包统计。主要看RcvbufErrors和SndbufErrors。如果两
  • 最好将发送端和接收端布置到不同电脑上(经过互联网最佳),以演示丢包的可能性.在本机环路(127.1.1.1)上测试时,发送1001个包,收到1001个包;作者将sender放在本地,在远程服务器上运行recver时发送1001个文字消息,但...
  • linux,socket通信,udp,接收缓冲区,recvfrom
  • QT中UDPSocket丢包问题

    千次阅读 2017-05-24 11:29:10
    Qt中的QUdpSocket发生严重丢包现象,在Linux下使用while死循环接收来解决,但存在CPU占用率太高的问题。
  • linux下双网卡udp收发通信,两个网口收到udp数据包后直接往源地址回复相同的数据,通过两个线程实现双网口并行工作,两个网卡工作在不同的网段
  • QT中UDPSocket丢包问题(续)

    千次阅读 2018-04-17 21:02:58
    之前描述了Qt中编写UDP收发程序的丢包问题,见http://blog.csdn.net/rabbitjerry/article/details/72674458后来终于得到了彻底解决,并且在Windows操作系统和Linux操作系统下均得到了验证。一、解决思路1.在程序中...
  • linux 系统 UDP 丢包

    2018-10-20 17:28:02
    1、 linux 系统接收网络报文的过程介绍 ● 首先网络报文通过物理网线发送到网卡● 网络驱动程序会把网络中的报文读出来放到 ring buffer 中,这个过程使用 DMA(Direct Memory Access),不需要 CPU 参与● 内核从 ...
  • 基于UDP SOCKET 统计丢包

    热门讨论 2011-11-22 15:59:41
    基于数据报套接字的C/S模型通信,客户端向服务器发送数据报并回射给客户端,统计丢包率。
  • UDP主要丢包原因及具体问题分析

    万次阅读 多人点赞 2015-08-28 00:20:44
    UDP主要丢包原因及具体问题分析   一、主要丢包原因   1、接收端处理时间过长导致丢包:调用recv方法接收端收到数据后,处理数据花了一些时间,处理完后再次调用recv方法,在这二次调用间隔里,发过来的包可能...
  • udp丢包问题排查

    2021-02-01 20:47:47
    背景: 类似于实时语音转译文本的产品,录音软件将客户端的语音流推送至后台服务,由后端服务转译后推送至客户端界面,后端服务使用到了redis,但是不和...后端服务排查发现,录音软件推送过来的udp包有丢失问题..
  • 最近工作中遇到某个服务器应用程序 UDP 丢包,在排查过程中查阅了很多资料,总结出来这篇文章,供更多人参考。 在开始之前,我们先用一张图解释 linux 系统接收网络报文的过程。 首先网络报文通过物理网线发送到...
  • 转自:...linux 系统 UDP 丢包问题分析思路 最近工作中遇到某个服务器应用程序 UDP 丢包,在排查过程中查阅了很多资料,总结出来这篇文章,供...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 11,440
精华内容 4,576
关键字:

linuxudp发送丢包

linux 订阅