亚洲视频二区_亚洲欧洲日本天天堂在线观看_日韩一区二区在线观看_中文字幕不卡一区

公告:魔扣目錄網為廣大站長提供免費收錄網站服務,提交前請做好本站友鏈:【 網站目錄:http://www.430618.com 】, 免友鏈快審服務(50元/站),

點擊這里在線咨詢客服
新站提交
  • 網站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會員:747

Netty:遇到TCP發(fā)送緩沖區(qū)滿了 寫半包操作該如何處理

什么是寫半包

寫半包:一份數(shù)據(jù),一次發(fā)送沒有把他全部發(fā)送,需要循環(huán)發(fā)送,那么第一次的操作稱為寫半包

什么情況下會出現(xiàn)寫半包:

發(fā)送方發(fā)送200byte,但是接收方只能接受100byte,因此發(fā)送方只會發(fā)送小于100byte的數(shù)據(jù)。

說到這里,機智的小伙伴已經想到了這跟TCP滑動窗口和消息中間件中常見的消息堆積是一個道理。

總的來說:接收方頂不住來自發(fā)送方的數(shù)據(jù)壓力

image.png 對?.NETty來說就是,這個時刻TCP發(fā)送緩沖區(qū)滿了,無法再接收整包數(shù)據(jù),剩下的數(shù)據(jù)則會通過Channel去監(jiān)聽寫操作,當觸發(fā)寫操作的時候,再把這部分數(shù)據(jù)給帶上,那么這部分數(shù)據(jù)才完整地傳輸。

Netty中的寫半包處理

前提知識:Netty中的網絡數(shù)據(jù)讀寫,都先經過ByteBuf image-20230227222618518

  • 讀操作:從ByteBuf中讀取數(shù)據(jù)
  • 寫操作:將數(shù)據(jù)寫入到ByteBuf,然后再通過其他方式把ByteBuf的數(shù)據(jù)寫入(#doWrite

Netty中的網路操作都是通過Channel和里面聚合的對象Unsafe對象進行操作,簡單介紹一下。

Channel

Channel的作用:給Netty用來進行網絡網絡

JDK 也有自己原生的Channel,但是為了方便框架擴展使用,Netty采用的是封裝了一層Facade(門面模式)。

最重要的是能夠支持Netty的自定義Channel來應對不同的業(yè)務場景。

Channel會被注冊到EventLoop上,在注冊的時候定義好感興趣的事件,他采用的是基于事件觸發(fā)的方式,當Channel上觸發(fā)相對應的事件時,就會主動回調通知,然后交給對應的ChannelHandler進行處理。

由于本篇講的是寫半包,因此不再過多解釋。

image.png

總的來說: Channel就是Netty用來處理網絡數(shù)據(jù)流的

回到本篇的主題:寫半包

AbstractNioByteChannel

主要負責處理寫半包

總的流程如圖:

image.png

ChannelOutboundBuffer:環(huán)形發(fā)送數(shù)組

  1. 不停地從ChannelOutboundBuffer讀取數(shù)據(jù),看是否有可以發(fā)送的數(shù)據(jù)

  2. 如果有,并且是ByteBuf類型的,可以選擇發(fā)送數(shù)據(jù)

    • 如果一次發(fā)送沒有發(fā)送完,則采取一定次數(shù)的循環(huán)發(fā)送(寫半包)
  3. 數(shù)據(jù)最后還是沒有發(fā)送完,則會開一條新線程專門進行剩余數(shù)據(jù)的發(fā)送

  4. 在最后會去同步數(shù)據(jù)寫入進度

源碼解析 #doWrite

image-20230311150751449

不停地去環(huán)形發(fā)送數(shù)組里面取數(shù)據(jù)出來

  • 如果是空了,代表發(fā)送完了,把寫標志位置空(clearOpWrite

image-20230311150858669

如果不是空數(shù)據(jù),則判斷是不是ByteBuf數(shù)據(jù)

  • 對其進行強轉,若可讀字節(jié)數(shù)是0,代表消息不可讀(reidIndex >= writeIndex),則把他在環(huán)形發(fā)送數(shù)組中移除

第一次讀的時候,會先去獲取循環(huán)發(fā)送次數(shù)writeSpinCount。循環(huán)發(fā)送次數(shù)就是指:第一次發(fā)送沒有完成時(寫半包)進行循環(huán)發(fā)送的次數(shù)。

給他設置一個閾值,為的就是當循環(huán)發(fā)送的時候,IO線程會一直嘗試寫操作,此時IO線程無法處理其他操作,相當于局部阻塞、死鎖、假死的情況

像這種處理手法非常常見,比如一般我們會給分布式鎖設置一個鎖的超時時間,除此之外還需要設置一個客戶端的超時時間,避免客戶端在拿到鎖的時候,這把鎖已經過期了。客戶端的超時時間會比鎖的超時時間要短

image-20230311151404816

然后就是進行循環(huán)發(fā)送了

image-20230311151426008

消息發(fā)送操作完成時候,會調用ChannelOutboundBuffer更新發(fā)送進度的消息,并且還會判斷是否需要寫半包處理

image-20230311151525404

如果沒有發(fā)完,則設置寫半包標識位,啟動專門的寫半包線程繼續(xù)發(fā)后續(xù)的消息

總結

寫半包問題本質上是:對于接收方來說,來自發(fā)送方的數(shù)據(jù)壓力太大了,因此不得不采取的一種降保護措施

可以在發(fā)送方進行解決、也可以在接收方進行解決

Netty并沒有采取說,遇到TCP緩沖區(qū)滿了之后,這個數(shù)據(jù)包就等下一次再等發(fā),而是能發(fā)多少就發(fā)多少,不夠的 下次再發(fā),是一種追求性能的選擇。

像消息中間件遇到消息堆積問題,在消接收方(消費者)增大消費的速度,比如:加消費隊列或擴充消費者群組等。

又或者限制發(fā)送方(生產者)的發(fā)送速度,比如TCP的滑動窗口。

所以互聯(lián)想的技術都是有相關聯(lián)的,能看到互相的影子。


 

分享到:
標簽:TCP
用戶無頭像

網友整理

注冊時間:

網站:5 個   小程序:0 個  文章:12 篇

  • 51998

    網站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

趕快注冊賬號,推廣您的網站吧!
最新入駐小程序

數(shù)獨大挑戰(zhàn)2018-06-03

數(shù)獨一種數(shù)學游戲,玩家需要根據(jù)9

答題星2018-06-03

您可以通過答題星輕松地創(chuàng)建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學四六

運動步數(shù)有氧達人2018-06-03

記錄運動步數(shù),積累氧氣值。還可偷

每日養(yǎng)生app2018-06-03

每日養(yǎng)生,天天健康

體育訓練成績評定2018-06-03

通用課目體育訓練成績評定