01
—
Netty介紹
1.Netty簡介
Netty是由JBOSS提供的一個java開源框架。
Netty是一個高性能、異步事件驅動的NIO框架,它提供了對TCP、UDP和文件傳輸的支持。作為當前最流行的NIO框架,Netty在互聯網領域、大數據分佈式計算領域、遊戲行業、通信行業等獲得了廣泛的應用,一些業界著名的開源組件也基於Netty的NIO框架構建(文章尾有詳細介紹)。
2.Netty的特點
- 高併發
Netty是一款基於NIO(Nonblocking I/O,非阻塞IO)開發的網絡通信框架,對比於BIO(Blocking I/O,阻塞IO),他的併發性能得到了很大提高 。
- 傳輸快
Netty的傳輸快其實也是依賴了NIO的一個特性——零拷貝。
- 封裝好
Netty封裝了NIO操作的很多細節,提供易於使用的API。
02
—
為什麼選擇Netty
JDK 原生也有一套網絡應用程序 API,但是存在一系列問題,主要如下:
1)NIO 的類庫和 API 繁雜,使用麻煩:你需要熟練掌握 Selector、ServerSocketChannel、SocketChannel、ByteBuffer 等。
2)需要具備其他的額外技能做鋪墊:例如熟悉 Java 多線程編程,因為 NIO 編程涉及到 Reactor 模式,你必須對多線程和網路編程非常熟悉,才能編寫出高質量的 NIO 程序。
3)可靠性能力補齊,開發工作量和難度都非常大:例如客戶端面臨斷連重連、網絡閃斷、半包讀寫、失敗緩存、網絡擁塞和異常碼流的處理等等。NIO 編程的特點是功能開發相對容易,但是可靠性能力補齊工作量和難度都非常大。
4)JDK NIO 的 Bug:例如臭名昭著的 Epoll Bug,它會導致 Selector 空輪詢,最終導致 CPU 100%。官方聲稱在 JDK 1.6 版本的 update 18 修復了該問題,但是直到 JDK 1.7 版本該問題仍舊存在,只不過該 Bug 發生概率降低了一些而已,它並沒有被根本解決。
03
—
Netty框架的優勢
- API使用簡單,開發門檻低;
- 功能強大,預置了多種編解碼功能,支持多種主流協議;
- 定製能力強,可以通過ChannelHandler對通信框架進行靈活地擴展;
- 性能高,通過與其他業界主流的NIO框架對比,Netty的綜合性能最優;
- 成熟、穩定,Netty修復了已經發現的所有JDK NIO BUG,業務開發人員不需要再為NIO的BUG而煩惱;
- 社區活躍,版本迭代週期短,發現的BUG可以被及時修復,同時,更多的新功能會加入;
- 經歷了大規模的商業應用考驗,質量得到驗證。在互聯網、大數據、網絡遊戲、企業應用、電信軟件等眾多行業得到成功商用,證明了它已經完全能夠滿足不同行業的商業應用了。
04
—
Netty的架構設計
總體結構
Netty 採用了比較典型的三層網絡架構進行設計,邏輯架構圖如下所示:
1)傳輸服務:支持 BIO 和 NIO;
2)容器集成:支持 OSGI、JBossMC、Spring、Guice 容器;
3)協議支持:HTTP、Protobuf、二進制、文本、WebSocket 等一系列常見協議都支持。還支持通過實行編碼解碼邏輯來實現自定義協議;
4)Core 核心:可擴展事件模型、通用通信 API、支持零拷貝的 ByteBuf 緩衝對象。
05
—
Netty的高性能設計
1.高性能的三大要素
1) 傳輸:用什麼樣的通道將數據發送給對方,BIO、NIO或者AIO,IO模型在很大程度上決定了框架的性能。
2) 協議:採用什麼樣的通信協議,HTTP或者內部私有協議。協議的選擇不同,性能模型也不同。相比於公有協議,內部私有協議的性能通常可以被設計的更優。
3) 線程:數據報如何讀取?讀取之後的編解碼在哪個線程進行,編解碼後的消息如何派發,Reactor線程模型的不同,對性能的影響也非常大。
2.IO模型
Netty的I/O模型基於非阻塞I/O實現,底層依賴的是JDK NIO框架的Selector。
3.Reactor線程模型
關於Java NIO 構造Reator模式,Doug lea在《Scalable IO in Java》中給了很好的闡述,這裡截取PPT對Reator模式的實現進行說明。
1)Reactor單線程模型:Reactor單線程模型,指的是所有的I/O操作都在同一個NIO線程上面完成。對於一些小容量應用場景,可以使用單線程模型。
2)Reactor多線程模型:Rector多線程模型與單線程模型最大的區別就是有一組NIO線程處理I/O操作。主要用於高併發、大業務量場景。
3)主從Reactor多線程模型:主從Reactor線程模型的特點是服務端用於接收客戶端連接的不再是個1個單獨的NIO線程,而是一個獨立的NIO線程池。利用主從NIO線程模型,可以解決1個服務端監聽線程無法有效處理所有客戶端連接的性能不足問題。
4.Netty的線程模型
說完了Reactor的三種模型,那麼Netty是哪一種呢?其實Netty的線程模型是Reactor模型的變種,那就是去掉線程池的第三種形式的變種,這也是Netty NIO的默認模式。
06
—
Netty的核心組件
Netty應用中必不可少的組件:
- Bootstrap or ServerBootstrap
- EventLoop
- EventLoopGroup
- ChannelPipeline
- Channel
- Future or ChannelFuture
- ChannelInitializer
- ChannelHandler
1.Bootstrap
一個Netty應用通常由一個Bootstrap開始,它主要作用是配置整個Netty程序,串聯起各個組件。
Handler,為了支持各種協議和處理數據的方式,便誕生了Handler組件。Handler主要用來處理各種事件,這裡的事件很廣泛,比如可以是連接、數據接收、異常、數據轉換等。
2.ChannelInboundHandler
一個最常用的Handler。這個Handler的作用就是處理接收到數據時的事件,也就是說,我們的業務邏輯一般就是寫在這個Handler裡面的,ChannelInboundHandler就是用來處理我們的核心業務邏輯。
3.ChannelInitializer
當一個鏈接建立時,我們需要知道怎麼來接收或者發送數據,當然,我們有各種各樣的Handler實現來處理它,那麼ChannelInitializer便是用來配置這些Handler,它會提供一個ChannelPipeline,並把Handler加入到ChannelPipeline。
4.ChannelPipeline
一個Netty應用基於ChannelPipeline機制,這種機制需要依賴於EventLoop和EventLoopGroup,因為它們三個都和事件或者事件處理相關。
EventLoops的目的是為Channel處理IO操作,一個EventLoop可以為多個Channel服務。EventLoopGroup會包含多個EventLoop。
5.Channel
代表了一個Socket鏈接,或者其它和IO操作相關的組件,它和EventLoop一起用來參與IO處理。
6.Future
在Netty中所有的IO操作都是異步的,因此,你不能立刻得知消息是否被正確處理,但是我們可以過一會等它執行完成或者直接註冊一個監聽,具體的實現就是通過Future和ChannelFutures,他們可以註冊一個監聽,當操作執行成功或失敗時監聽會自動觸發。
總之,所有的操作都會返回一個ChannelFuture。
07
—
Netty的應用場景
1.互聯網行業
在分佈式系統中,各個節點之間需要遠程服務調用,高性能的RPC框架必不可少,Netty作為異步高新能的通信框架,往往作為基礎通信組件被這些RPC框架使用。
典型的應用有:阿里分佈式服務框架Dubbo的RPC框架使用Dubbo協議進行節點間通信,Dubbo協議默認使用Netty作為基礎通信組件,用於實現各進程節點之間的內部通信。
除了 Dubbo 之外,淘寶的消息中間件 RocketMQ 的消息生產者和消息消費者之間,也採用 Netty 進行高性能、異步通信。
2.遊戲行業
無論是手遊服務端還是大型的網絡遊戲,Java語言得到了越來越廣泛的應用。Netty作為高性能的基礎通信組件,它本身提供了TCP/UDP和HTTP協議棧。
非常方便定製和開發私有協議棧,賬號登錄服務器,地圖服務器之間可以方便的通過Netty進行高性能的通信。
3.大數據領域
經典的Hadoop的高性能通信和序列化組件Avro的RPC框架,默認採用Netty進行跨界點通信,它的Netty Service基於Netty框架二次封裝實現。
-end-