Netty學(xué)習(xí)分享

Netty基本概念?

Netty是一個(gè)高性能、異步事件驅(qū)動(dòng)的NIO框架,它提供了對TCP、UDP和文件傳輸?shù)闹С?,作為一個(gè)異步NIO框架,Netty的所有IO操作都是異步非阻塞的,通過Future-Listener機(jī)制,用戶可以方便的主動(dòng)獲取或者通過通知機(jī)制獲得IO操作結(jié)果。

作為當(dāng)前最流行的NIO框架,Netty在互聯(lián)網(wǎng)領(lǐng)域、大數(shù)據(jù)分布式計(jì)算領(lǐng)域、游戲行業(yè)、通信行業(yè)等獲得了廣泛的應(yīng)用,一些業(yè)界著名的開源組件也基于Netty的NIO框架構(gòu)建。如:Dubbo、 RocketMQ、Hadoop的Avro、Spark等。

官網(wǎng):https://netty.io/

業(yè)界主要的使用:

Hadoop Spark

RocketMQ

Dubbo gRPC

ElasticSearch

大體架構(gòu)

Netty為什么性能好

1、I/O傳輸模型

用什么樣的通道將數(shù)據(jù)發(fā)送給對方,是BIO、NIO還是AIO,I/O傳輸模型在很大程度上決定了框架的性能。

Netty對三種I/O方式的支持

Not-blocking IO

即用戶需要不斷地調(diào)用read,嘗試讀取socket中的數(shù)據(jù),直到讀取成功后,才繼續(xù)處理接收的數(shù)據(jù)。整個(gè)IO請求的過程中,雖然用戶線程每次發(fā)起IO請求后可以立即返回,但是為了等到數(shù)據(jù),仍需要不斷地輪詢、重復(fù)請求

IO多路復(fù)用

通過Reactor的方式,可以將用戶線程輪詢IO操作狀態(tài)的工作統(tǒng)一交給handle_events事件循環(huán)進(jìn)行處理。用戶線程注冊事件處理器之后可以繼續(xù)執(zhí)行做其他的工作(異步),而Reactor線程負(fù)責(zé)調(diào)用內(nèi)核的select函數(shù)檢查socket狀態(tài)。當(dāng)有socket被激活時(shí),則通知相應(yīng)的用戶線程(或執(zhí)行用戶線程的回調(diào)函數(shù)),執(zhí)行handle_event進(jìn)行數(shù)據(jù)讀取、處理的工作。由于select函數(shù)是阻塞的,因此多路IO復(fù)用模型也被稱為異步阻塞IO模型。注意,這里的所說的阻塞是指select函數(shù)執(zhí)行時(shí)線程被阻塞,而不是指socket。一般在使用IO多路復(fù)用模型時(shí),socket都是設(shè)置為NONBLOCK的,不過這并不會(huì)產(chǎn)生影響,因?yàn)橛脩舭l(fā)起IO請求時(shí),數(shù)據(jù)已經(jīng)到達(dá)了,用戶線程一定不會(huì)被阻塞。

異步IO

異步IO模型中,用戶線程直接使用內(nèi)核提供的異步IO API發(fā)起read請求,且發(fā)起后立即返回,繼續(xù)執(zhí)行用戶線程代碼。不過此時(shí)用戶線程已經(jīng)將調(diào)用的AsynchronousOperation和CompletionHandler注冊到內(nèi)核,然后操作系統(tǒng)開啟獨(dú)立的內(nèi)核線程去處理IO操作。當(dāng)read請求的數(shù)據(jù)到達(dá)時(shí),由內(nèi)核負(fù)責(zé)讀取socket中的數(shù)據(jù),并寫入用戶指定的緩沖區(qū)中。最后內(nèi)核將read的數(shù)據(jù)和用戶線程注冊的CompletionHandler分發(fā)給內(nèi)部Proactor,Proactor將IO完成的信息通知給用戶線程(一般通過調(diào)用用戶線程注冊的完成事件處理函數(shù)),完成異步IO。

2、數(shù)據(jù)協(xié)議

用什么樣的通訊協(xié)議,是HTTP,還是內(nèi)部私有協(xié)議。協(xié)議的選擇不同,性能也就不同,一般來說內(nèi)部私有協(xié)議比公有協(xié)議的性能更高。

編解碼器

業(yè)界主流的編解碼框架:

Google Protobuf:支持Java、C++、Python三種語言,高效的編碼性能,結(jié)構(gòu)化數(shù)據(jù)存儲(chǔ)格式(XML,JSON等)

Facebook Thrift:適用于靜態(tài)的數(shù)據(jù)交換,需要先確定好它的數(shù)據(jù)結(jié)構(gòu)。結(jié)構(gòu)變化后需要重新編譯IDL文件,這也是Thrift的弱項(xiàng)。

JBoss Marshalling:是一個(gè)Java對象的序列化API,修正了JDK自帶的序列化包的很多問題,但又保持跟java.io.Serializable接口的兼容。

Hessian:一個(gè)輕量級的remoting onhttp工具,使用簡單的方法提供了RMI的功能,采用的是二進(jìn)制RPC協(xié)議。

TCP粘包/拆包及Netty如何解決

粘包/拆包問題描述

解決方式:

消息定長,例如每個(gè)報(bào)文的大小為固定長度200字節(jié),如果不夠,空位補(bǔ)空格。

在包尾增加回車換行符進(jìn)行分割,例如FTP協(xié)議。

將消息分為消息頭和消息體,消息頭中包含消息長度的字段,通常設(shè)計(jì)思路為消息頭的第一個(gè)字段使用int32來表示消息的總長度

3、線程模型

線程模型涉及如何讀取數(shù)據(jù)包,讀取之后的編解碼在哪個(gè)線程中進(jìn)行,編解碼后的消息如何派發(fā)等方面。線程模型設(shè)計(jì)不同,對性能也會(huì)產(chǎn)生非常大的影響。

Netty線程模型

(1)Reactor單線程模型

(2)Reactor多線程模型

(3)Reactor主從模型

Netty的線程模型并不是一成不變,它實(shí)際取決于用戶的啟動(dòng)參數(shù)配置。通過設(shè)置不同的啟動(dòng)參數(shù),Netty可以同時(shí)支持Reactor單線程模型、多線程模型和主從模型。

Ref:

深入探秘 Netty、Kafka 中的零拷貝技術(shù)!_石杉的架構(gòu)筆記-CSDN博客

IO多路復(fù)用機(jī)制詳解 - Yeang - 博客園

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容