一文搞定Netty接收數(shù)據(jù)的原理
? 點擊上方“JavaEdge”,關(guān)注公眾號

1 Netty讀數(shù)據(jù)的技巧

1.1 AdaptiveRecvByteBufAllocator

自適應(yīng)數(shù)據(jù)大小的分配器。打水時,拿多大桶去裝?

小了不夠,大了浪費。所以根據(jù)自己實際裝預(yù)估下次情況,從而決定下次帶多大桶。
AdaptiveRecvByteBufAllocator對bytebuf的猜測
直接放大
謹慎縮小( 需連續(xù)2次判斷)
1.2 defaultMaxMessagesPerRead

連續(xù)讀。
排隊打水時,假設(shè)當(dāng)前桶裝滿了,這時你會覺得可能還要打點水才夠用,所以直接拿個新桶等裝,而非回家,直到后面出現(xiàn)
有桶沒有裝滿
裝了很多桶了,需要給別人留個機會
等原因才停止,回家。

2 執(zhí)行流程

如下都是worker線程的事。
多路復(fù)用器( Selector )接收到OP_READ事件
處理OP_READ事件:NioSocketChannel.NioSocketChannelUnsafe.read()
分配一個初始1024字節(jié)的byte buffer來接受數(shù)據(jù)
從Channel接受數(shù)據(jù)到byte buffer
記錄實際接受數(shù)據(jù)大小,調(diào)整下次分配byte buffer大小
觸發(fā) pipeline.fireChannelRead(byteBuf)把讀取到的數(shù)據(jù)傳播出去
判斷接受byte buffer是否滿載而歸:是,嘗試繼續(xù)讀取直到?jīng)]有數(shù)據(jù)或滿16次;否,結(jié)束本輪讀取,等待下次OP_READ事件
和連接事件類似,我們肯定還是主要在 NioEventLoop
此處先處理的 OP_ACCEPT 建立連接事件,直接讓它過了
這次來的才是處理讀請求的

3 讀取數(shù)據(jù)的根本 API

sun.nio.ch.SocketChannellmpl#read(java.nio.ByteBuffer)


4 read方法區(qū)別

NioSocketChannel#read 讀數(shù)據(jù)
NioServerSocketChannel#read 創(chuàng)建連接

5 fireChannelRead區(qū)別

pipeline.fireChannelReadComplete()
一次讀事件處理完成pipeline fireChannelRead(byteBuf)
一次讀數(shù)據(jù)完成, 一次讀事件處理可能會包含多次讀數(shù)據(jù)操作

6 為啥最多只嘗試讀16次?

給別人留機會。
往期推薦

目前交流群已有?800+人,旨在促進技術(shù)交流,可關(guān)注公眾號添加筆者微信邀請進群
喜歡文章,點個“在看、點贊、分享”素質(zhì)三連支持一下~
