Netty是什么?
鏈接:https://www.zhihu.com/question/24322387/answer/78947405
來源:知乎
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。
Netty是什么?
1)本質:JBoss做的一個Jar包
2)目的:快速開發高性能、高可靠性的網絡服務器和客戶端程序
3)優點:提供異步的、事件驅動的網絡應用程序框架和工具
通俗的說:一個好使的處理Socket的東東
如果沒有Netty?
遠古:
java.net + java.io
近代:
java.nio
其他:
Mina,Grizzly
與Mina相比有什么優勢?
1、都是Trustin Lee的作品,Netty更晚;
2、Mina將內核和一些特性的聯系過于緊密,使得用戶在不需要這些特性的時候無法脫離,相比下性能會有所下降,Netty解決了這個設計問題;
3、Netty的文檔更清晰,很多Mina的特性在Netty里都有;
4、Netty更新周期更短,新版本的發布比較快;
5、它們的架構差別不大,Mina靠apache生存,而Netty靠jboss,和jboss的結合度非常高,Netty有對google protocal buf的支持,有更完整的ioc容器支持(spring,guice,jbossmc和osgi);
6、Netty比Mina使用起來更簡單,Netty里你可以自定義的處理upstream events 或/和 downstream events,可以使用decoder和encoder來解碼和編碼發送內容;
7、Netty和Mina在處理UDP時有一些不同,Netty將UDP無連接的特性暴露出來;而Mina對UDP進行了高級層次的抽象,可以把UDP當成"面向連接"的協議,而要Netty做到這一點比較困難。
-----------------------------------------------------------------------------------------------------------------------------------------Netty的特性
1)設計
統一的API,適用于不同的協議(阻塞和非阻塞)
基于靈活、可擴展的事件驅動模型
高度可定制的線程模型
可靠的無連接數據Socket支持(UDP)
2)性能
更好的吞吐量,低延遲
更省資源
盡量減少不必要的內存拷貝
3)安全
完整的SSL/TLS和STARTTLS的支持
能在Applet與Android的限制環境運行良好
4)健壯性
不再因過快、過慢或超負載連接導致OutOfMemoryError
不再有在高速網絡環境下NIO讀寫頻率不一致的問題
5)易用
完善的JavaDoc,用戶指南和樣例
簡潔簡單
僅信賴于JDK1.5
-------------------------------------------------------------------------------------------------------------------------------------------
Netty 在哪些行業得到了應用?
-
互聯網行業:隨著網站規模的不斷擴大,系統并發訪問量也越來越高,傳統基于 Tomcat 等 Web 容器的垂直架構已經無法滿足需求,需要拆分應用進行服務化,以提高開發和維護效率。從組網情況看,垂直的架構拆分之后,系統采用分布式部署,各個節點之間需要遠程服務調用,高性能的 RPC 框架必不可少,Netty 作為異步高性能的通信框架,往往作為基礎通信組件被這些 RPC 框架使用。
典型的應用有:阿里分布式服務框架 Dubbo 的 RPC 框架使用 Dubbo 協議進行節點間通信,Dubbo 協議默認使用 Netty 作為基礎通信組件,用于實現各進程節點之間的內部通信。它的架構圖如下:
<img src="https://pic3.zhimg.com/50/0033448fdced8b3c3897e1a41b4dfa10_hd.jpg" data-rawwidth="533" data-rawheight="356" class="origin_image zh-lightbox-thumb" width="533" data-original="https://pic3.zhimg.com/0033448fdced8b3c3897e1a41b4dfa10_r.jpg">
其中,服務提供者和服務消費者之間,服務提供者、服務消費者和性能統計節點之間使用 Netty 進行異步/同步通信。
除了 Dubbo 之外,淘寶的消息中間件 RocketMQ 的消息生產者和消息消費者之間,也采用 Netty 進行高性能、異步通信。
除了阿里系和淘寶系之外,很多其它的大型互聯網公司或者電商內部也已經大量使用 Netty 構建高性能、分布式的網絡服務器。
-
游戲行業:無論是手游服務端、還是大型的網絡游戲,Java 語言得到了越來越廣泛的應用。Netty 作為高性能的基礎通信組件,它本身提供了 TCP/UDP 和 HTTP 協議棧,非常方便定制和開發私有協議棧。賬號登陸服務器、地圖服務器之間可以方便的通過 Netty 進行高性能的通信,架構示意圖如下:
<img src="https://pic2.zhimg.com/50/9adabad98edc4b4e9001e2fc63d6da87_hd.jpg" data-rawwidth="494" data-rawheight="196" class="origin_image zh-lightbox-thumb" width="494" data-original="https://pic2.zhimg.com/9adabad98edc4b4e9001e2fc63d6da87_r.jpg">
圖1-2 Netty 在游戲服務器架構中的應用
-
大數據領域:經典的 Hadoop 的高性能通信和序列化組件 Avro 的 RPC 框架,默認采用 Netty 進行跨節點通信,它的 Netty Service 基于 Netty 框架二次封裝實現。
大數據計算往往采用多個計算節點和一個/N個匯總節點進行分布式部署,各節點之間存在海量的數據交換。由于 Netty 的綜合性能是目前各個成熟 NIO 框架中最高的,因此,往往會被選中用作大數據各節點間的通信。
-
企業軟件:企業和 IT 集成需要 ESB,Netty 對多協議支持、私有協議定制的簡潔性和高性能是 ESB RPC 框架的首選通信組件。事實上,很多企業總線廠商會選擇 Netty 作為基礎通信組件,用于企業的 IT 集成。
-
通信行業:Netty 的異步高性能、高可靠性和高成熟度的優點,使它在通信行業得到了大量的應用。
作為一個學Java的,如果沒有研究過Netty,那么你對Java語言的使用和理解僅僅停留在表面水平,會點SSH,寫幾個MVC,訪問數據庫和緩存,這些只是初等Java程序員干的事。如果你要進階,想了解Java服務器的深層高階知識,Netty絕對是一個必須要過的門檻。
有了Netty,你可以實現自己的HTTP服務器,FTP服務器,UDP服務器,RPC服務器,WebSocket服務器,Redis的Proxy服務器,MySQL的Proxy服務器等等。
如果你想知道Nginx是怎么寫出來的,如果你想知道Tomcat和Jetty是如何實現的,如果你也想實現一個簡單的Redis服務器,那都應該好好理解一下Netty,它們高性能的原理都是類似的。
我們回顧一下傳統的HTTP服務器的原理
- 創建一個ServerSocket,監聽并綁定一個端口
- 一系列客戶端來請求這個端口
- 服務器使用Accept,獲得一個來自客戶端的Socket連接對象
- 啟動一個新線程處理連接
- 讀Socket,得到字節流
- 解碼協議,得到Http請求對象
- 處理Http請求,得到一個結果,封裝成一個HttpResponse對象
- 編碼協議,將結果序列化字節流
- 寫Socket,將字節流發給客戶端
- 繼續循環步驟3
HTTP服務器之所以稱為HTTP服務器,是因為編碼解碼協議是HTTP協議,如果協議是Redis協議,那它就成了Redis服務器,如果協議是WebSocket,那它就成了WebSocket服務器,等等。
使用Netty你就可以定制編解碼協議,實現自己的特定協議的服務器。
上面我們說的是一個傳統的多線程服務器,這個也是Apache處理請求的模式。在高并發環境下,線程數量可能會創建太多,操作系統的任務調度壓力大,系統負載也會比較高。那怎么辦呢?
于是NIO誕生了,NIO并不是Java獨有的概念,NIO代表的一個詞匯叫著IO多路復用。它是由操作系統提供的系統調用,早期這個操作系統調用的名字是select,但是性能低下,后來漸漸演化成了Linux下的epoll和Mac里的kqueue。我們一般就說是epoll,因為沒有人拿蘋果電腦作為服務器使用對外提供服務。而Netty就是基于Java NIO技術封裝的一套框架。為什么要封裝,因為原生的Java NIO使用起來沒那么方便,而且還有臭名昭著的bug,Netty把它封裝之后,提供了一個易于操作的使用模式和接口,用戶使用起來也就便捷多了。
那NIO究竟是什么東西呢?
NIO的全稱是NoneBlocking IO,非阻塞IO,區別與BIO,BIO的全稱是Blocking IO,阻塞IO。那這個阻塞是什么意思呢?
- Accept是阻塞的,只有新連接來了,Accept才會返回,主線程才能繼
- Read是阻塞的,只有請求消息來了,Read才能返回,子線程才能繼續處理
- Write是阻塞的,只有客戶端把消息收了,Write才能返回,子線程才能繼續讀取下一個請求
所以傳統的多線程服務器是BlockingIO模式的,從頭到尾所有的線程都是阻塞的。這些線程就干等在哪里,占用了操作系統的調度資源,什么事也不干,是浪費。
那么NIO是怎么做到非阻塞的呢。它用的是事件機制。它可以用一個線程把Accept,讀寫操作,請求處理的邏輯全干了。如果什么事都沒得做,它也不會死循環,它會將線程休眠起來,直到下一個事件來了再繼續干活,這樣的一個線程稱之為NIO線程。
while true {events = takeEvents(fds) // 獲取事件,如果沒有事件,線程就休眠for event in events {if event.isAcceptable {doAccept() // 新鏈接來了} elif event.isReadable {request = doRead() // 讀消息if request.isComplete() {doProcess()}} elif event.isWriteable {doWrite() // 寫消息}}
}
NIO的流程大致就是上面的偽代碼描述的過程,跟實際真實的代碼有較多差異,不過對于初學者,這樣理解也是足夠了。
Netty是建立在NIO基礎之上,Netty在NIO之上又提供了更高層次的抽象。
在Netty里面,Accept連接可以使用單獨的線程池去處理,讀寫操作又是另外的線程池來處理。
Accept連接和讀寫操作也可以使用同一個線程池來進行處理。而請求處理邏輯既可以使用單獨的線程池進行處理,也可以跟放在讀寫線程一塊處理。線程池中的每一個線程都是NIO線程。用戶可以根據實際情況進行組裝,構造出滿足系統需求的并發模型。
Netty提供了內置的常用編解碼器,包括行編解碼器[一行一個請求],前綴長度編解碼器[前N個字節定義請求的字節長度],可重放解碼器[記錄半包消息的狀態],HTTP編解碼器,WebSocket消息編解碼器等等
Netty提供了一些列生命周期回調接口,當一個完整的請求到達時,當一個連接關閉時,當一個連接建立時,用戶都會收到回調事件,然后進行邏輯處理。
Netty可以同時管理多個端口,可以使用NIO客戶端模型,這些對于RPC服務是很有必要的。
Netty除了可以處理TCP Socket之外,還可以處理UDP Socket。
在消息讀寫過程中,需要大量使用ByteBuffer,Netty對ByteBuffer在性能和使用的便捷性上都進行了優化和抽象。
總之,Netty是Java程序員進階的必備神奇。如果你知其然,還想知其所以然,一定要好好研究下Netty。如果你覺得Java枯燥無謂,Netty則是重新開啟你對Java興趣大門的鑰匙。
總結
- 上一篇: 个性签名简短霸气超拽
- 下一篇: 一般小哈士奇要多少钱?