0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

tcp丢包究竟会带来多大的性能问题

科技绿洲 来源:Linux开发架构之路 作者:Linux开发架构之路 2023-11-08 16:16 次阅读

一个项目对接第三方接口数据。对方是TCP接口,发送数据频率很高。平均2毫秒发送三四千个字节。由于TCP协议的粘包拆包问题,我这里接收到的数据需要对粘包拆包按照对方数据的格式进行处理。对接了一段时间后发现,TCP连接会自动断开。由于我这里做了断开重连的逻辑。所以最终的现象就是一直在断开,重连,再断开,再重连。

向数据提供方咨询,数据提供方给出的反馈是数据消费不过来,造成数据积压后,他们的程序就会主动断开TCP连接。通过日志发现,我这里确实在断开前,消费数据出现了延迟。通过日志观察发现,接收数据的时候,比发送数据的时间慢了几秒,由于数据量很大,所以造成了积压,数据提供方就断开了连接。

问题分析

于是,问题的焦点就到了为何我的程序消费不过来数据呢?首先想到的就是我写的程序性能有问题,导致无法消费平均2毫秒产生的三四千个字节这个数据频率。由于粘包拆包程序是我自己自定义处理的,于是,我怀疑是自己的处理逻辑性能差。

通过研究发现,netty框架提供了针对于TCP粘包拆包的解析类。于是,我引入了netty框架,使用netty框架提供的LengthFieldBasedFrameDecoder解析器对接收到的数据进行处理。发现还是会出现延迟,消费不过来的现象发生。

由于netty接收数据后,对数据进行处理,默认是使用单线程来完成的。即接收TCP数据和处理粘包拆包是在一个线程中完成的。这是不是影响了消费的速率呢?于是,我写了两个线程,一个用于接收数据,然后把接收到的数据存入一个集合容器中。紧接着继续拉取下一批数据。另一个线程用于处理集合容器中的数据。这种解决方案依旧不行,还是延迟消费数据。

难道是接收了数据,往集合容器中存放这个操作,也影响了性能,使其消费不过来了?于是,我把程序改成了只接收数据,然后打印一个接收字节数的日志,其余的操作再也没有了。尝试这种操作是否可以不自动断开TCP连接。因为不自动断开TCP连接证明数据消费没有延迟。

令人费解的事情发生了,纯接收数据,就打印个接收字节数的日志,还是会自动断开TCP连接。这就表明,无论我怎么优化代码,它都会延迟消费。这就不是我代码的问题而引起的消费延迟了。因为我肯定要去接收TCP的数据。而现在纯接收数据,不做任何处理,就发生了延迟了。这说明已经不是我程序代码的问题了。

起初怀疑的对象是操作系统是不是消费不过来了?一定是操作系统先从网络中拉取数据,我的应用程序再从操纵系统中获取数据的。如果操作系统这个层面就消费不过来了,那么我的程序肯定也消费不过来。因为我用的服务器是Window Server系统,所以,将程序部署到了一台linux服务器上进行纯接收数据,不做任何处理的测试。最后发现,依旧会自动断开TCP连接。

服务器这个猜测也失败了。因为数据提供方也会消费这些数据,而他们的系统没有出现过这种自动断开的情况。说明不是操作系统消费不过来了。

于是,我把目光转到了接收字节数量的日志上。发现大多数日志输出的都是一次拉取1460个字节。还发现会有一次拉取几万个字节的情况出现。而最大的拉取量是65536个字节,不会比这个字节再大了。即使我在程序里定义的读取数据的byte数组的长度是10万,程序最多也是拉取65536个字节。

搞不懂这些数字代表的含义,可以看看下面这篇文章:

深入理解 TCP 协议:从原理到实战【超详细】-上

深入理解 TCP 协议:从原理到实战【超详细】-下

这里解释一下上述日志中几个数字的含义。首先,1460是以太网的MTU是1500,去掉40个字节的TCP头和IP头,业务数据的长度就是1460个字节。即一个包最长的业务数据就是1460。而程序每次大部分都读取1460个字节。证明滑动窗口里的数据是没有积压的。也就是说当程序读1460个字节的时候,说明是消费的过来的。因为如果数据积压了,那么必定在滑动窗口里有很多个字节,甚至把滑动窗口填满。那么程序单次拉取字节数,就不可能是1460个,而是比1460个要多。所以当程序每次拉取也是1460的时候,说明发一次数据,就可以消费一次数据,是不存在延迟现象的。

那么日志中小于1460个数据拉取又是如何发生的呢?加入TCP的发送方一次发送了2000个字节的业务数据,而在物理层的以太网中,只能发送1460个字节。那么就会对数据进行分片。前1460个字节为一个包,发送获取了,剩余的540个字节是另一个包发送过去。这就造成了少于1460个字节的拉取情况出现。其本质也是发送了多少数据就拉取了多少数据,不存在延迟现象。

那么延迟到底是怎么发生的呢?这就要分析那些一次拉取上万个字节的数据的情况是如何发生的了。通过观察发现,每次拉取上万个字节的数据,日志都会卡顿几十毫秒甚至更长才会拉取一次数据。由于停顿的这几十毫秒一直有数据发送过来,所以接收滑动窗口的数据就会一直增加。当停顿结束后再次拉取数据时,就从滑动窗口里拉取了更多的数据回来。所以就有上万个字节的数据了。那程序为何会停顿,不拉取数据了呢?

通过wireshark抓包工具发现,当TCP出现丢包时,程序就不拉取数据了。因为当TCP丢包后,由于滑动窗口的存在,在滑动窗口范围内,还会继续接收发送过来的数据。但是因为丢包了,所以应用程序就不会再消费数据了。此时,我这里的操作系统会给发送方反馈丢包信息(TCP dup ack),默认情况下是发送三次TCP dup ack后,发送方就会立马重传丢包的数据。但是观察wireshark发现,丢包后,重传50多次TCP dup ack后,发送方才会返回丢包的数据。这就说明,TCP dup ack反馈消息也在一直丢失,直到发送了50多次后,才收到3条TCP dup ack信息。当然,如果一直收不到TCP dup ack信息,那么只有等到超时时间后,发送方主动再次发送丢包数据了。可见,这里的网络环境是有多差。

那这就分析出了消费延迟的根本问题所在。因为TCP发生了丢包,导致了应用程序的停顿,无法读取TCP丢包后的数据。而丢包的反馈TCP dup ack又无法第一时间被发送方接收到,所以接收方应用程序卡顿的时间就会变长。而TCP产生数据的频率又是很高的,所以在停顿的这个期间,就产生了很多的数据。当丢包的数据被发送方发送过来后,应用程序从丢包位置读取数据,而此时丢包的位置后面已经产生了大量的数据,所以造成了消费的延迟。

分析到这里,问题的本质似乎找到了。但是还有一个现象不可忽略。那就是每次TCP主动断开的位置,都不是程序停顿的位置,也不是一次拉取几万个字节的位置。而是一次拉取1460个字节的位置。而上面我们又分析道,一次拉取1460个字节,说明消费是能跟的上的,没有积压数据。那为何还会消费延迟呢?

这就涉及到了TCP网络拥堵的处理机制。只要发生了丢包,TCP就认为当前的网络环境不佳,TCP发送方会根据自己的机制,主动减少发送量,避免对网络造成更大的压力。当发生丢包后,应用程序停顿了几秒。但是停顿结束后,会有几次拉取几万个字节数据的情况,这几次拉取,就会赶上积压的数据的消费速率。也就是这里会有延迟,但是拉取几次大数据量后,消费就赶上来了。而TCP发送方认为当前的网络环境不佳,所以发送方主动减少了发送的吞吐量。这就造成了发送方产生了大量的数据,但是发送的数据量很小。这就造成了发送方数据的积压。当积压到一定程度后,发送方的应用程序就断开了连接。

总结

综上所述,发生消费延迟问题,是因为TCP频繁丢包,触发了TCP的拥堵处理机制,导致发送方发送量减少,数据产生了积压,造成了消费的延迟。

上面还有一点提到数据积压后,最大的拉取量是65536,这是因为操作系统所能承受的单次数据拉取量,就是65535个,如果频繁的接收大于65535字节的数据,会使操作系统崩溃。所以这个值是操作系统进行的限制。而我上面又说到,数据提供方也在消费这个数据,但是他们没有出现过延迟。是因为他们在本地进行的数据消费。即数据发送和接收都是一个服务器。这种情况是不会走物理层的,也不会经过网卡,所以单次传输就没有1460这个限制了,就升级到了65535这个限制。而且本地传输也不会出现丢包现象。所以他们消费没出现延迟。

感悟

TCP为了保证数据的安全性,发生丢包后做出的一系列处理会影响性能。而在大数量的情况下,会把性能的影响放大。所以,在选择协议时,要综合分析,选择最合适的协议。例如本次的业务场景,完全不适合用TCP协议,而适合用UDP协议。因为接收到数据后,也会根据逻辑过滤掉大多数的数据,而是保留一部分数据。所以对数据的安全性要求不是那么高,使用UDP协议,允许丢失一部分数据,就不会出现这种消费延迟的问题了。

抓包记录

记录一下使用wireshark抓包发现问题的过程。

首先,选择要监听的网卡,然后输入过滤器,过滤ip(host xxx),只查看发送数据的ip的TCP协议。

图片

然后,进入网络监控页面,在顶部的过滤器中,输入tcp,表示只监控tcp协议。

图片

第二列的TIme字段,默认不是yyyy-MM-dd HH:mm:ss格式的,需要手动调成此格式,方便查看数据发送的时间:

图片

然后,开始分析接收到的具体数据:

图片

如上图所示,TCP Previous segment not captured就代表接收方收到了后面的数据,但是前面的数据还没收到。即前面的数据发生了丢包。这个提示是wireshark自己分析给出的提示,而且还标黑了,说明接收数据发生了丢包。

发生丢包后,接收方就给发送方发送TCP Dup Ack信息,告诉接收方丢包了。默认情况是发送三次,接收方就会把丢包数据返回,但是如上图所示,发送了11次,还没收到丢包数据。

图片

直到发送了58次以后,才收到发送方返回的 TCP Fast Retransmission信息,这表明是收到了丢包的数据。

此外,在统计–>专家信息中,wireshark也统计了各种情况发生的次数,如下图:

图片

图片

第一行就是丢包的次数,可见,发生了85次丢包。丢包现象很严重。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 接口
    +关注

    关注

    33

    文章

    8575

    浏览量

    151016
  • 数据
    +关注

    关注

    8

    文章

    7002

    浏览量

    88942
  • TCP
    TCP
    +关注

    关注

    8

    文章

    1353

    浏览量

    79055
  • 程序
    +关注

    关注

    117

    文章

    3785

    浏览量

    81004
收藏 人收藏

    评论

    相关推荐

    常见的网络故障定位⽅法

    本期分享一个比较常见的⽹络问题--。例如我们去ping⼀个⽹站,如果能ping通,且⽹站返回信息全⾯,则说明与⽹站服务器的通信是畅通的,如果ping不通,或者⽹站返回的信息不全等,则很可能是数据
    的头像 发表于 12-07 09:48 1812次阅读
    常见的网络<b class='flag-5'>丢</b><b class='flag-5'>包</b>故障定位⽅法

    为什么ESP8266 TCP透传过程会

    为什么ESP8266 TCP透传过程会
    发表于 07-09 07:55

    esp8266透传tcp如何防止

    esp8266透传tcp如何防止
    发表于 09-25 08:09

    AD9122 REFIO管脚没有外接负载,如果没有按手册外接0.1uF电容滤波,对AD9122性能究竟会有什么不良影响?

    请问: AD9122 REFIO管脚没有外接负载,如果没有按手册外接0.1uF电容滤波,对AD9122性能究竟会有什么不良影响,谢谢!
    发表于 12-15 07:14

    网卡

    网卡率(Loss Tolerance或packet loss rate)是指测试中
    发表于 12-26 12:09 1302次阅读

    网络数据的原因及摄像机的原因

    不少人在使用网络和监控摄像系统的时候都有遇到过数据的情况,数据的原因是多种多样的,以下就为大家介绍一下网络数据
    的头像 发表于 01-11 09:27 1.3w次阅读

    Linux应用的延时和模拟

      本文将要介绍的是 RHCA 中的一个 BDP 的测试,这也是公司很常用的一种延时和的模拟,你可以测试你的应用软件在不同的情况下的性能,也可以测试你 tcp/ip
    发表于 04-02 14:38 486次阅读

    直角走线究竟会对信号传输产生多大的影响?资料下载

    电子发烧友网为你提供直角走线究竟会对信号传输产生多大的影响?资料下载的电子资料下载,更有其他相关的电路图、源代码、课件教程、中文资料、英文资料、参考设计、用户指南、解决方案等资料,希望可以帮助到广大的电子工程师们。
    发表于 03-31 08:40 3次下载
    直角走线<b class='flag-5'>究竟会</b>对信号传输产生<b class='flag-5'>多大</b>的影响?资料下载

    PCB直角走线究竟会对信号传输产生多大的影响?资料下载

    电子发烧友网为你提供PCB直角走线究竟会对信号传输产生多大的影响?资料下载的电子资料下载,更有其他相关的电路图、源代码、课件教程、中文资料、英文资料、参考设计、用户指南、解决方案等资料,希望可以帮助到广大的电子工程师们。
    发表于 04-08 08:55 12次下载
    PCB直角走线<b class='flag-5'>究竟会</b>对信号传输产生<b class='flag-5'>多大</b>的影响?资料下载

    深入分析Linux网络问题

    通常会带来严重的性能下降,特别是对 TCP 来说,通常意味着网络拥塞和重传,进而还会导致网络延迟增大、吞吐降低。
    的头像 发表于 05-04 15:08 1394次阅读
    深入分析Linux网络<b class='flag-5'>丢</b><b class='flag-5'>包</b>问题

    问题如何解决?方法在这里

    关于的问题无线通信最常见的问题就是,无论是简单原始的433MHz通信,还是高精尖的5G信号,都会有
    的头像 发表于 10-14 10:23 2981次阅读
    <b class='flag-5'>丢</b><b class='flag-5'>包</b>问题如何解决?方法在这里

    网络问题解析

    什么是 数据在Internet上是以数据为单位传输的,单位为字节,数据在网络上传输,受网络设备,网络质量等原因的影响,使得接收到的数据少于发送出去的数据,造成
    的头像 发表于 11-09 15:10 909次阅读
    网络<b class='flag-5'>丢</b><b class='flag-5'>包</b>问题解析

    网络故障如何定位

    引言 本期分享一个比较常见的网络问题--。例如我们去ping一个网站,如果能ping通,且网站返回信息全面,则说明与网站服务器的通信是畅通的,如果ping不通,或者网站返回的信息不全等,则很可能
    的头像 发表于 11-10 11:27 1275次阅读
    网络<b class='flag-5'>丢</b><b class='flag-5'>包</b>故障如何定位

    网络问题分析

    通常会带来严重的性能下降,特别是对 TCP 来说,通常意味着网络拥塞和重传,进而还会导致网络延迟增大、吞吐降低。 一、 哪里可能
    的头像 发表于 11-13 11:24 1009次阅读
    网络<b class='flag-5'>丢</b><b class='flag-5'>包</b>问题分析

    网络率正常范围及其影响因素

    网络率正常范围及其影响因素 网络率是评估网络性能和稳定性的重要指标之一。 一、网络
    的头像 发表于 12-29 14:45 6146次阅读