0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

tcp丟包究竟會帶來多大的性能問題

科技綠洲 ? 來源:Linux開發(fā)架構(gòu)之路 ? 作者:Linux開發(fā)架構(gòu)之路 ? 2023-11-08 16:16 ? 次閱讀

一個(gè)項(xiàng)目對接第三方接口數(shù)據(jù)。對方是TCP接口,發(fā)送數(shù)據(jù)頻率很高。平均2毫秒發(fā)送三四千個(gè)字節(jié)。由于TCP協(xié)議的粘包拆包問題,我這里接收到的數(shù)據(jù)需要對粘包拆包按照對方數(shù)據(jù)的格式進(jìn)行處理。對接了一段時(shí)間后發(fā)現(xiàn),TCP連接會自動斷開。由于我這里做了斷開重連的邏輯。所以最終的現(xiàn)象就是一直在斷開,重連,再斷開,再重連。

向數(shù)據(jù)提供方咨詢,數(shù)據(jù)提供方給出的反饋是數(shù)據(jù)消費(fèi)不過來,造成數(shù)據(jù)積壓后,他們的程序就會主動斷開TCP連接。通過日志發(fā)現(xiàn),我這里確實(shí)在斷開前,消費(fèi)數(shù)據(jù)出現(xiàn)了延遲。通過日志觀察發(fā)現(xiàn),接收數(shù)據(jù)的時(shí)候,比發(fā)送數(shù)據(jù)的時(shí)間慢了幾秒,由于數(shù)據(jù)量很大,所以造成了積壓,數(shù)據(jù)提供方就斷開了連接。

問題分析

于是,問題的焦點(diǎn)就到了為何我的程序消費(fèi)不過來數(shù)據(jù)呢?首先想到的就是我寫的程序性能有問題,導(dǎo)致無法消費(fèi)平均2毫秒產(chǎn)生的三四千個(gè)字節(jié)這個(gè)數(shù)據(jù)頻率。由于粘包拆包程序是我自己自定義處理的,于是,我懷疑是自己的處理邏輯性能差。

通過研究發(fā)現(xiàn),netty框架提供了針對于TCP粘包拆包的解析類。于是,我引入了netty框架,使用netty框架提供的LengthFieldBasedFrameDecoder解析器對接收到的數(shù)據(jù)進(jìn)行處理。發(fā)現(xiàn)還是會出現(xiàn)延遲,消費(fèi)不過來的現(xiàn)象發(fā)生。

由于netty接收數(shù)據(jù)后,對數(shù)據(jù)進(jìn)行處理,默認(rèn)是使用單線程來完成的。即接收TCP數(shù)據(jù)和處理粘包拆包是在一個(gè)線程中完成的。這是不是影響了消費(fèi)的速率呢?于是,我寫了兩個(gè)線程,一個(gè)用于接收數(shù)據(jù),然后把接收到的數(shù)據(jù)存入一個(gè)集合容器中。緊接著繼續(xù)拉取下一批數(shù)據(jù)。另一個(gè)線程用于處理集合容器中的數(shù)據(jù)。這種解決方案依舊不行,還是延遲消費(fèi)數(shù)據(jù)。

難道是接收了數(shù)據(jù),往集合容器中存放這個(gè)操作,也影響了性能,使其消費(fèi)不過來了?于是,我把程序改成了只接收數(shù)據(jù),然后打印一個(gè)接收字節(jié)數(shù)的日志,其余的操作再也沒有了。嘗試這種操作是否可以不自動斷開TCP連接。因?yàn)椴蛔詣訑嚅_TCP連接證明數(shù)據(jù)消費(fèi)沒有延遲。

令人費(fèi)解的事情發(fā)生了,純接收數(shù)據(jù),就打印個(gè)接收字節(jié)數(shù)的日志,還是會自動斷開TCP連接。這就表明,無論我怎么優(yōu)化代碼,它都會延遲消費(fèi)。這就不是我代碼的問題而引起的消費(fèi)延遲了。因?yàn)槲铱隙ㄒソ邮誘CP的數(shù)據(jù)。而現(xiàn)在純接收數(shù)據(jù),不做任何處理,就發(fā)生了延遲了。這說明已經(jīng)不是我程序代碼的問題了。

起初懷疑的對象是操作系統(tǒng)是不是消費(fèi)不過來了?一定是操作系統(tǒng)先從網(wǎng)絡(luò)中拉取數(shù)據(jù),我的應(yīng)用程序再從操縱系統(tǒng)中獲取數(shù)據(jù)的。如果操作系統(tǒng)這個(gè)層面就消費(fèi)不過來了,那么我的程序肯定也消費(fèi)不過來。因?yàn)槲矣玫姆?wù)器是Window Server系統(tǒng),所以,將程序部署到了一臺linux服務(wù)器上進(jìn)行純接收數(shù)據(jù),不做任何處理的測試。最后發(fā)現(xiàn),依舊會自動斷開TCP連接。

服務(wù)器這個(gè)猜測也失敗了。因?yàn)閿?shù)據(jù)提供方也會消費(fèi)這些數(shù)據(jù),而他們的系統(tǒng)沒有出現(xiàn)過這種自動斷開的情況。說明不是操作系統(tǒng)消費(fèi)不過來了。

于是,我把目光轉(zhuǎn)到了接收字節(jié)數(shù)量的日志上。發(fā)現(xiàn)大多數(shù)日志輸出的都是一次拉取1460個(gè)字節(jié)。還發(fā)現(xiàn)會有一次拉取幾萬個(gè)字節(jié)的情況出現(xiàn)。而最大的拉取量是65536個(gè)字節(jié),不會比這個(gè)字節(jié)再大了。即使我在程序里定義的讀取數(shù)據(jù)的byte數(shù)組的長度是10萬,程序最多也是拉取65536個(gè)字節(jié)。

搞不懂這些數(shù)字代表的含義,可以看看下面這篇文章:

深入理解 TCP 協(xié)議:從原理到實(shí)戰(zhàn)【超詳細(xì)】-上

深入理解 TCP 協(xié)議:從原理到實(shí)戰(zhàn)【超詳細(xì)】-下

這里解釋一下上述日志中幾個(gè)數(shù)字的含義。首先,1460是以太網(wǎng)的MTU是1500,去掉40個(gè)字節(jié)的TCP頭和IP頭,業(yè)務(wù)數(shù)據(jù)的長度就是1460個(gè)字節(jié)。即一個(gè)包最長的業(yè)務(wù)數(shù)據(jù)就是1460。而程序每次大部分都讀取1460個(gè)字節(jié)。證明滑動窗口里的數(shù)據(jù)是沒有積壓的。也就是說當(dāng)程序讀1460個(gè)字節(jié)的時(shí)候,說明是消費(fèi)的過來的。因?yàn)槿绻麛?shù)據(jù)積壓了,那么必定在滑動窗口里有很多個(gè)字節(jié),甚至把滑動窗口填滿。那么程序單次拉取字節(jié)數(shù),就不可能是1460個(gè),而是比1460個(gè)要多。所以當(dāng)程序每次拉取也是1460的時(shí)候,說明發(fā)一次數(shù)據(jù),就可以消費(fèi)一次數(shù)據(jù),是不存在延遲現(xiàn)象的。

那么日志中小于1460個(gè)數(shù)據(jù)拉取又是如何發(fā)生的呢?加入TCP的發(fā)送方一次發(fā)送了2000個(gè)字節(jié)的業(yè)務(wù)數(shù)據(jù),而在物理層的以太網(wǎng)中,只能發(fā)送1460個(gè)字節(jié)。那么就會對數(shù)據(jù)進(jìn)行分片。前1460個(gè)字節(jié)為一個(gè)包,發(fā)送獲取了,剩余的540個(gè)字節(jié)是另一個(gè)包發(fā)送過去。這就造成了少于1460個(gè)字節(jié)的拉取情況出現(xiàn)。其本質(zhì)也是發(fā)送了多少數(shù)據(jù)就拉取了多少數(shù)據(jù),不存在延遲現(xiàn)象。

那么延遲到底是怎么發(fā)生的呢?這就要分析那些一次拉取上萬個(gè)字節(jié)的數(shù)據(jù)的情況是如何發(fā)生的了。通過觀察發(fā)現(xiàn),每次拉取上萬個(gè)字節(jié)的數(shù)據(jù),日志都會卡頓幾十毫秒甚至更長才會拉取一次數(shù)據(jù)。由于停頓的這幾十毫秒一直有數(shù)據(jù)發(fā)送過來,所以接收滑動窗口的數(shù)據(jù)就會一直增加。當(dāng)停頓結(jié)束后再次拉取數(shù)據(jù)時(shí),就從滑動窗口里拉取了更多的數(shù)據(jù)回來。所以就有上萬個(gè)字節(jié)的數(shù)據(jù)了。那程序?yàn)楹螘nD,不拉取數(shù)據(jù)了呢?

通過wireshark抓包工具發(fā)現(xiàn),當(dāng)TCP出現(xiàn)丟包時(shí),程序就不拉取數(shù)據(jù)了。因?yàn)楫?dāng)TCP丟包后,由于滑動窗口的存在,在滑動窗口范圍內(nèi),還會繼續(xù)接收發(fā)送過來的數(shù)據(jù)。但是因?yàn)閬G包了,所以應(yīng)用程序就不會再消費(fèi)數(shù)據(jù)了。此時(shí),我這里的操作系統(tǒng)會給發(fā)送方反饋丟包信息(TCP dup ack),默認(rèn)情況下是發(fā)送三次TCP dup ack后,發(fā)送方就會立馬重傳丟包的數(shù)據(jù)。但是觀察wireshark發(fā)現(xiàn),丟包后,重傳50多次TCP dup ack后,發(fā)送方才會返回丟包的數(shù)據(jù)。這就說明,TCP dup ack反饋消息也在一直丟失,直到發(fā)送了50多次后,才收到3條TCP dup ack信息。當(dāng)然,如果一直收不到TCP dup ack信息,那么只有等到超時(shí)時(shí)間后,發(fā)送方主動再次發(fā)送丟包數(shù)據(jù)了??梢?,這里的網(wǎng)絡(luò)環(huán)境是有多差。

那這就分析出了消費(fèi)延遲的根本問題所在。因?yàn)門CP發(fā)生了丟包,導(dǎo)致了應(yīng)用程序的停頓,無法讀取TCP丟包后的數(shù)據(jù)。而丟包的反饋TCP dup ack又無法第一時(shí)間被發(fā)送方接收到,所以接收方應(yīng)用程序卡頓的時(shí)間就會變長。而TCP產(chǎn)生數(shù)據(jù)的頻率又是很高的,所以在停頓的這個(gè)期間,就產(chǎn)生了很多的數(shù)據(jù)。當(dāng)丟包的數(shù)據(jù)被發(fā)送方發(fā)送過來后,應(yīng)用程序從丟包位置讀取數(shù)據(jù),而此時(shí)丟包的位置后面已經(jīng)產(chǎn)生了大量的數(shù)據(jù),所以造成了消費(fèi)的延遲。

分析到這里,問題的本質(zhì)似乎找到了。但是還有一個(gè)現(xiàn)象不可忽略。那就是每次TCP主動斷開的位置,都不是程序停頓的位置,也不是一次拉取幾萬個(gè)字節(jié)的位置。而是一次拉取1460個(gè)字節(jié)的位置。而上面我們又分析道,一次拉取1460個(gè)字節(jié),說明消費(fèi)是能跟的上的,沒有積壓數(shù)據(jù)。那為何還會消費(fèi)延遲呢?

這就涉及到了TCP網(wǎng)絡(luò)擁堵的處理機(jī)制。只要發(fā)生了丟包,TCP就認(rèn)為當(dāng)前的網(wǎng)絡(luò)環(huán)境不佳,TCP發(fā)送方會根據(jù)自己的機(jī)制,主動減少發(fā)送量,避免對網(wǎng)絡(luò)造成更大的壓力。當(dāng)發(fā)生丟包后,應(yīng)用程序停頓了幾秒。但是停頓結(jié)束后,會有幾次拉取幾萬個(gè)字節(jié)數(shù)據(jù)的情況,這幾次拉取,就會趕上積壓的數(shù)據(jù)的消費(fèi)速率。也就是這里會有延遲,但是拉取幾次大數(shù)據(jù)量后,消費(fèi)就趕上來了。而TCP發(fā)送方認(rèn)為當(dāng)前的網(wǎng)絡(luò)環(huán)境不佳,所以發(fā)送方主動減少了發(fā)送的吞吐量。這就造成了發(fā)送方產(chǎn)生了大量的數(shù)據(jù),但是發(fā)送的數(shù)據(jù)量很小。這就造成了發(fā)送方數(shù)據(jù)的積壓。當(dāng)積壓到一定程度后,發(fā)送方的應(yīng)用程序就斷開了連接。

總結(jié)

綜上所述,發(fā)生消費(fèi)延遲問題,是因?yàn)門CP頻繁丟包,觸發(fā)了TCP的擁堵處理機(jī)制,導(dǎo)致發(fā)送方發(fā)送量減少,數(shù)據(jù)產(chǎn)生了積壓,造成了消費(fèi)的延遲。

上面還有一點(diǎn)提到數(shù)據(jù)積壓后,最大的拉取量是65536,這是因?yàn)椴僮飨到y(tǒng)所能承受的單次數(shù)據(jù)拉取量,就是65535個(gè),如果頻繁的接收大于65535字節(jié)的數(shù)據(jù),會使操作系統(tǒng)崩潰。所以這個(gè)值是操作系統(tǒng)進(jìn)行的限制。而我上面又說到,數(shù)據(jù)提供方也在消費(fèi)這個(gè)數(shù)據(jù),但是他們沒有出現(xiàn)過延遲。是因?yàn)樗麄冊诒镜剡M(jìn)行的數(shù)據(jù)消費(fèi)。即數(shù)據(jù)發(fā)送和接收都是一個(gè)服務(wù)器。這種情況是不會走物理層的,也不會經(jīng)過網(wǎng)卡,所以單次傳輸就沒有1460這個(gè)限制了,就升級到了65535這個(gè)限制。而且本地傳輸也不會出現(xiàn)丟包現(xiàn)象。所以他們消費(fèi)沒出現(xiàn)延遲。

感悟

TCP為了保證數(shù)據(jù)的安全性,發(fā)生丟包后做出的一系列處理會影響性能。而在大數(shù)量的情況下,會把性能的影響放大。所以,在選擇協(xié)議時(shí),要綜合分析,選擇最合適的協(xié)議。例如本次的業(yè)務(wù)場景,完全不適合用TCP協(xié)議,而適合用UDP協(xié)議。因?yàn)榻邮盏綌?shù)據(jù)后,也會根據(jù)邏輯過濾掉大多數(shù)的數(shù)據(jù),而是保留一部分?jǐn)?shù)據(jù)。所以對數(shù)據(jù)的安全性要求不是那么高,使用UDP協(xié)議,允許丟失一部分?jǐn)?shù)據(jù),就不會出現(xiàn)這種消費(fèi)延遲的問題了。

抓包記錄

記錄一下使用wireshark抓包發(fā)現(xiàn)問題的過程。

首先,選擇要監(jiān)聽的網(wǎng)卡,然后輸入過濾器,過濾ip(host xxx),只查看發(fā)送數(shù)據(jù)的ip的TCP協(xié)議。

圖片

然后,進(jìn)入網(wǎng)絡(luò)監(jiān)控頁面,在頂部的過濾器中,輸入tcp,表示只監(jiān)控tcp協(xié)議。

圖片

第二列的TIme字段,默認(rèn)不是yyyy-MM-dd HH:mm:ss格式的,需要手動調(diào)成此格式,方便查看數(shù)據(jù)發(fā)送的時(shí)間:

圖片

然后,開始分析接收到的具體數(shù)據(jù):

圖片

如上圖所示,TCP Previous segment not captured就代表接收方收到了后面的數(shù)據(jù),但是前面的數(shù)據(jù)還沒收到。即前面的數(shù)據(jù)發(fā)生了丟包。這個(gè)提示是wireshark自己分析給出的提示,而且還標(biāo)黑了,說明接收數(shù)據(jù)發(fā)生了丟包。

發(fā)生丟包后,接收方就給發(fā)送方發(fā)送TCP Dup Ack信息,告訴接收方丟包了。默認(rèn)情況是發(fā)送三次,接收方就會把丟包數(shù)據(jù)返回,但是如上圖所示,發(fā)送了11次,還沒收到丟包數(shù)據(jù)。

圖片

直到發(fā)送了58次以后,才收到發(fā)送方返回的 TCP Fast Retransmission信息,這表明是收到了丟包的數(shù)據(jù)。

此外,在統(tǒng)計(jì)–>專家信息中,wireshark也統(tǒng)計(jì)了各種情況發(fā)生的次數(shù),如下圖:

圖片

圖片

第一行就是丟包的次數(shù),可見,發(fā)生了85次丟包。丟包現(xiàn)象很嚴(yán)重。

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報(bào)投訴
  • 接口
    +關(guān)注

    關(guān)注

    33

    文章

    8645

    瀏覽量

    151396
  • 數(shù)據(jù)
    +關(guān)注

    關(guān)注

    8

    文章

    7081

    瀏覽量

    89180
  • TCP
    TCP
    +關(guān)注

    關(guān)注

    8

    文章

    1372

    瀏覽量

    79142
  • 程序
    +關(guān)注

    關(guān)注

    117

    文章

    3792

    瀏覽量

    81161
收藏 人收藏

    評論

    相關(guān)推薦

    常見的網(wǎng)絡(luò)故障定位?法

    本期分享一個(gè)比較常見的?絡(luò)問題--。例如我們?nèi)ing?個(gè)?站,如果能ping通,且?站返回信息全?,則說明與?站服務(wù)器的通信是暢通的,如果ping不通,或者?站返回的信息不全等,則很可能是數(shù)據(jù)
    的頭像 發(fā)表于 12-07 09:48 ?1869次閱讀
    常見的網(wǎng)絡(luò)<b class='flag-5'>丟</b><b class='flag-5'>包</b>故障定位?法

    為什么ESP8266 TCP透傳過程會

    為什么ESP8266 TCP透傳過程會?
    發(fā)表于 07-09 07:55

    esp8266透傳tcp如何防止?

    esp8266透傳tcp如何防止
    發(fā)表于 09-25 08:09

    AD9122 REFIO管腳沒有外接負(fù)載,如果沒有按手冊外接0.1uF電容濾波,對AD9122性能究竟會有什么不良影響?

    請問: AD9122 REFIO管腳沒有外接負(fù)載,如果沒有按手冊外接0.1uF電容濾波,對AD9122性能究竟會有什么不良影響,謝謝!
    發(fā)表于 12-15 07:14

    網(wǎng)卡

    網(wǎng)卡率(Loss Tolerance或packet loss rate)是指測試中
    發(fā)表于 12-26 12:09 ?1304次閱讀

    網(wǎng)絡(luò)數(shù)據(jù)的原因及攝像機(jī)的原因

    不少人在使用網(wǎng)絡(luò)和監(jiān)控?cái)z像系統(tǒng)的時(shí)候都有遇到過數(shù)據(jù)的情況,數(shù)據(jù)的原因是多種多樣的,以下就為大家介紹一下網(wǎng)絡(luò)數(shù)據(jù)
    的頭像 發(fā)表于 01-11 09:27 ?1.3w次閱讀

    Linux應(yīng)用的延時(shí)和模擬

      本文將要介紹的是 RHCA 中的一個(gè) BDP 的測試,這也是公司很常用的一種延時(shí)和的模擬,你可以測試你的應(yīng)用軟件在不同的情況下的性能,也可以測試你 tcp/ip
    發(fā)表于 04-02 14:38 ?500次閱讀

    直角走線究竟會對信號傳輸產(chǎn)生多大的影響?資料下載

    電子發(fā)燒友網(wǎng)為你提供直角走線究竟會對信號傳輸產(chǎn)生多大的影響?資料下載的電子資料下載,更有其他相關(guān)的電路圖、源代碼、課件教程、中文資料、英文資料、參考設(shè)計(jì)、用戶指南、解決方案等資料,希望可以幫助到廣大的電子工程師們。
    發(fā)表于 03-31 08:40 ?3次下載
    直角走線<b class='flag-5'>究竟會</b>對信號傳輸產(chǎn)生<b class='flag-5'>多大</b>的影響?資料下載

    PCB直角走線究竟會對信號傳輸產(chǎn)生多大的影響?資料下載

    電子發(fā)燒友網(wǎng)為你提供PCB直角走線究竟會對信號傳輸產(chǎn)生多大的影響?資料下載的電子資料下載,更有其他相關(guān)的電路圖、源代碼、課件教程、中文資料、英文資料、參考設(shè)計(jì)、用戶指南、解決方案等資料,希望可以幫助到廣大的電子工程師們。
    發(fā)表于 04-08 08:55 ?12次下載
    PCB直角走線<b class='flag-5'>究竟會</b>對信號傳輸產(chǎn)生<b class='flag-5'>多大</b>的影響?資料下載

    深入分析Linux網(wǎng)絡(luò)問題

    通常會帶來嚴(yán)重的性能下降,特別是對 TCP 來說,通常意味著網(wǎng)絡(luò)擁塞和重傳,進(jìn)而還會導(dǎo)致網(wǎng)絡(luò)延遲增大、吞吐降低。
    的頭像 發(fā)表于 05-04 15:08 ?1413次閱讀
    深入分析Linux網(wǎng)絡(luò)<b class='flag-5'>丟</b><b class='flag-5'>包</b>問題

    問題如何解決?方法在這里

    關(guān)于的問題無線通信最常見的問題就是,無論是簡單原始的433MHz通信,還是高精尖的5G信號,都會有
    的頭像 發(fā)表于 10-14 10:23 ?3065次閱讀
    <b class='flag-5'>丟</b><b class='flag-5'>包</b>問題如何解決?方法在這里

    網(wǎng)絡(luò)問題解析

    什么是 數(shù)據(jù)在Internet上是以數(shù)據(jù)為單位傳輸?shù)?,單位為字?jié),數(shù)據(jù)在網(wǎng)絡(luò)上傳輸,受網(wǎng)絡(luò)設(shè)備,網(wǎng)絡(luò)質(zhì)量等原因的影響,使得接收到的數(shù)據(jù)少于發(fā)送出去的數(shù)據(jù),造成
    的頭像 發(fā)表于 11-09 15:10 ?935次閱讀
    網(wǎng)絡(luò)<b class='flag-5'>丟</b><b class='flag-5'>包</b>問題解析

    網(wǎng)絡(luò)故障如何定位

    引言 本期分享一個(gè)比較常見的網(wǎng)絡(luò)問題--。例如我們?nèi)ing一個(gè)網(wǎng)站,如果能ping通,且網(wǎng)站返回信息全面,則說明與網(wǎng)站服務(wù)器的通信是暢通的,如果ping不通,或者網(wǎng)站返回的信息不全等,則很可能
    的頭像 發(fā)表于 11-10 11:27 ?1326次閱讀
    網(wǎng)絡(luò)<b class='flag-5'>丟</b><b class='flag-5'>包</b>故障如何定位

    網(wǎng)絡(luò)問題分析

    通常會帶來嚴(yán)重的性能下降,特別是對 TCP 來說,通常意味著網(wǎng)絡(luò)擁塞和重傳,進(jìn)而還會導(dǎo)致網(wǎng)絡(luò)延遲增大、吞吐降低。 一、 哪里可能
    的頭像 發(fā)表于 11-13 11:24 ?1040次閱讀
    網(wǎng)絡(luò)<b class='flag-5'>丟</b><b class='flag-5'>包</b>問題分析

    網(wǎng)絡(luò)率正常范圍及其影響因素

    網(wǎng)絡(luò)率正常范圍及其影響因素 網(wǎng)絡(luò)率是評估網(wǎng)絡(luò)性能和穩(wěn)定性的重要指標(biāo)之一。 一、網(wǎng)絡(luò)
    的頭像 發(fā)表于 12-29 14:45 ?6423次閱讀