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

    文章

    7651

    浏览量

    148547
  • 数据
    +关注

    关注

    8

    文章

    6514

    浏览量

    87614
  • TCP
    TCP
    +关注

    关注

    8

    文章

    1273

    浏览量

    78307
  • 程序
    +关注

    关注

    114

    文章

    3631

    浏览量

    79560
收藏 人收藏

    评论

    相关推荐

    ZIGBEE节点同时发送问题

    ZIGBEE节点同时发送问题ZIGBEE听别人说节点几个同时发送就会,我用的是网络状,纯路由节点,路由发送数据是不定时的发送给协调器,那么我该怎么减少
    发表于 03-23 10:38

    labview 用TCP/IP协议发送数据速度慢并且

    1000个字节外加标志位以及表示长度的字节,共1012个字节为一发送,为什么会出先发送时间超过了50秒,而且有时候会,而且很严重,这和TCP Write模块上的延时有关吗,还是说
    发表于 11-18 08:20

    cc2540 的问题

    本人用的是公司自己做的板子。发现发送数据间隔相同,TI的开发板能够不,但是我们自己做的板子却比较严重。只有加大发送数据的间隔才能使自己做的板子不
    发表于 05-14 01:03

    请问Z-stack SerialApp通讯是什么原因?

    ,也就几KB),还是会发生,而且一旦发生,通讯就好像完全堵上,后续的数据都没法传输,要等好几秒才能又继续。请问照成这样的原因是什么?buffer小了?有没有改进的方法(减少率,
    发表于 08-13 06:11

    ESP8266 TCP透传有时接收的数据

    到的数据长度,是1460,正好是一个TCP的长度。于是我猜测,由于BIN文件太大,拆分了多个TCP,而网络原因,第一个发完后第二个
    发表于 04-18 06:35

    同样1ynm制程的LPDDR4X和LPDDR5在性能上两者究竟多大区别?

    LPDDR5究竟是什么?有什么特点?同样1ynm制程的LPDDR4X和LPDDR5在性能上两者究竟多大区别?
    发表于 06-18 06:48

    使用6300EVK板子搭建LWIP TCP服务端,在响应客户端回传数据时无规律性的原因?

    使用官方6300EVK板子 搭建 LWIP TCP服务端在响应客户端回传数据时无规律性电脑PING连接也会
    发表于 05-26 08:10

    esp8266透传tcp如何防止

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

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

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

    直角走线会对信号传输产生多大的影响

    一般我们都会多次强调直角走线是PCB布线中要求尽量避免的情况,也几乎成为衡量布线好坏的标准之一,那么直角走线究竟会对信号传输产生多大的影响呢?
    的头像 发表于 05-25 11:02 7259次阅读
    直角走线会对信号传输产生<b class='flag-5'>多大</b>的影响

    企业上云后究竟会面临什么样的安全风险

    数据和各类服务向云端迁移不禁让很多企业开始重新思考自己的网络安全体系。企业上云后究竟会面临什么样的安全风险?
    发表于 11-26 14:21 2332次阅读

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

    直角走线一般是PCB布线中要求尽量避免的情况,也几乎成为衡量布线好坏的标准之一,那么直角走线究竟会对信号传输产生多大的影响呢?从原理上说,直角走线会使传输线的线宽发生变化,造成阻抗的不连续。其实
    的头像 发表于 07-27 15:13 5281次阅读

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

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

    Socket缓存如何影响TCP性能

    一直以来我们都知道socket的缓存会对tcp性能产生影响,也有无数文章告诉我们应该调大socke缓存。但是究竟多大?什么时候调?有哪些手段调?具体影响
    的头像 发表于 11-09 10:13 283次阅读