聽說96.5%的程序員都沒用過Netty
Netty介紹
Netty是一個基于Java的高性能網(wǎng)絡(luò)應(yīng)用框架,封裝了Java NIO的復(fù)雜性,提供了簡單而強(qiáng)大的網(wǎng)絡(luò)編程API,使得開發(fā)者能夠更方便地開發(fā)網(wǎng)絡(luò)應(yīng)用程序。
所以說學(xué)習(xí)Netty前先理解一下Java NIO是很有必要的,不然云里霧里的。
Netty有多優(yōu)秀呢?包括但不限于以下幾點(diǎn)
高性能的IO處理
如果基于Java NIO開發(fā)一個成熟的應(yīng)用,要非常注意如ByteBuffer內(nèi)存泄漏、Channel注冊連接、線程管理等問題。
而Netty能夠更好地處理連接管理、線程模型和內(nèi)存管理等方面的問題,提供更高的吞吐量和更低的延遲。
強(qiáng)大的功能擴(kuò)展
如果基于Java NIO寫一個HTTP協(xié)議、Websocket協(xié)議,那我們需要考慮格式、編解碼問題。
而Netty提供了豐富的擴(kuò)展點(diǎn),比如編解碼器、處理器和攔截器等,開發(fā)人員可以通過不同的配置搭建HTTP、WebSocket、TCP和RTSP等協(xié)議,也可以輕松地添加編解碼器,實(shí)現(xiàn)自定義協(xié)議。
可靠性和穩(wěn)定性
Netty具有良好的容錯能力和穩(wěn)定性,能夠處理各種網(wǎng)絡(luò)故障和異常情況,并提供了多種容錯和恢復(fù)機(jī)制,如斷線重連和心跳機(jī)制等。
總的來說,開發(fā)人員在開發(fā)網(wǎng)絡(luò)應(yīng)用程序時,使用Netty能夠更專注于業(yè)務(wù)邏輯。
下圖為Netty所支持的功能
圖片
Netty發(fā)展歷程
為了進(jìn)一步了解Netty,這里介紹一下Netty的前世今生。
- 2004年:Netty的前身Jboss Netty項目在JBoss公司內(nèi)部啟動,目標(biāo)是提供一個可擴(kuò)展的、易用的網(wǎng)絡(luò)編程框架。
- 2008年:Netty項目在JBoss公司內(nèi)部開源,并發(fā)布了第一個公開版本Netty 3.0。該版本主要針對TCP和HTTP協(xié)議進(jìn)行了支持。
- 2011年:Netty 3.2發(fā)布,引入了更多的特性和改進(jìn),包括更好的性能和更靈活的API設(shè)計。
- 2012年:Netty 4.0發(fā)布,這是一個重大的里程碑版本。在這個版本中,Netty進(jìn)行了全面的重構(gòu)和優(yōu)化,引入了新的API設(shè)計和更高級的特性。
- 2013年:Netty 4.0獲得了廣泛的認(rèn)可和采用,并成為了許多大型互聯(lián)網(wǎng)公司和項目的首選網(wǎng)絡(luò)編程框架。同年底發(fā)布了5.0.0.Alpha1,目標(biāo)是對Netty 4改進(jìn)和優(yōu)化。
- 2015年:Netty 5在開發(fā)過程中遇到了一些挑戰(zhàn)和技術(shù)難題,決定暫停Netty 5的開發(fā),并將重心轉(zhuǎn)移到Netty 4的改進(jìn)和維護(hù)上。
- 2016年:Netty 4.1發(fā)布,基于4.0版本進(jìn)一步改進(jìn)和優(yōu)化,提供了更好的性能和更多的功能。
目前有很多知名的項目都選用了Netty作為網(wǎng)絡(luò)通信的基礎(chǔ),比如知名的RPC框架Dubbo、gRPC,消息隊列Kafka、RocketMQ,搜索引擎Elasticsearch等,所以當(dāng)學(xué)習(xí)了解這些項目時,Netty會作為一個加分項。
Netty核心組件
因為Netty是基于Java NIO封裝的,更加的抽象,要使用Netty進(jìn)行開發(fā),必須要熟悉Netty中的幾個核心組件,下面一一介紹:
- Channel(通道):與Java NIO中的SocketChannel一樣,可以進(jìn)行數(shù)據(jù)的讀取和寫入。
- EventLoop(事件循環(huán)):EventLoop是Netty的事件處理機(jī)制,它負(fù)責(zé)處理各種事件,包括連接的建立與關(guān)閉、數(shù)據(jù)的讀取與寫入等。可以理解成Java NIO中的Selector監(jiān)聽socket的事件,只不過Netty是多線程處理,后面代碼中有體現(xiàn)。
- ChannelHandler(通道處理器):用來處理Channel中的事件和數(shù)據(jù)的組件,例如對數(shù)據(jù)編解碼、業(yè)務(wù)邏輯處理等。Netty提供了許多內(nèi)置的ChannelHandler,用于處理網(wǎng)絡(luò)連接和I/O操作。以下是一些常用的ChannelHandler:
ChannelInboundHandler:用于處理入站事件,例如連接建立、數(shù)據(jù)讀取等。
ChannelOutboundHandler:用于處理出站事件,例如數(shù)據(jù)寫入、連接關(guān)閉等。
SimpleChannelInboundHandler:繼承自ChannelInboundHandler,簡化了消息處理的邏輯。
SimpleChannelOutboundHandler:繼承自ChannelOutboundHandler,簡化了消息發(fā)送的邏輯。
HttpServerCodec:它負(fù)責(zé)處理 HTTP 請求和響應(yīng)的編解碼。
HttpObjectAggregator:將 HTTP 請求的多個部分合并成一個完整的 FullHttpRequest。
WebSocketServerProtocolHandler:處理 WebSocket 協(xié)議的握手和幀的編解碼。
- ChannelPipeline(通道管道):ChannelPipeline是一個事件處理器鏈,用于管理和執(zhí)行ChannelHandler,每個Channel都有一個對應(yīng)的Pipeline,當(dāng)數(shù)據(jù)進(jìn)入或離開Channel時,會經(jīng)過Pipeline中的一系列ChannelHandler進(jìn)行處理。
- ByteBuf(字節(jié)緩沖區(qū)):ByteBuf是Netty中的字節(jié)容器,用于高效地存儲和傳輸字節(jié)數(shù)據(jù)。與Java NIO的ByteBuffer相比,ByteBuf提供了更靈活的API和更高效的內(nèi)存管理。
- Future(異步操作結(jié)果):Netty中的操作都是異步的,F(xiàn)uture用來獲取操作的狀態(tài)和結(jié)果。
- Bootstrap(引導(dǎo)類):Bootstrap是啟動客戶端的類,負(fù)責(zé)配置和啟動客戶端的相關(guān)組件。
- ServerBootstrap(服務(wù)器引導(dǎo)類):ServerBootstrap是創(chuàng)建和啟動服務(wù)器的類,用于配置和管理服務(wù)器的各個組件。
Netty 編程示例
HTTP請求報文格式
下面以HTTP協(xié)議為例,用Netty編寫一個HTTP服務(wù)器。
在這之前,我們先用上篇文章的NIOServer接收一下瀏覽器的請求,大概是這樣的:
HTTP請求格式
可以看到接收到了一個HTTP請求的報文數(shù)據(jù),有請求行、請求頭和請求主體,這時候也能看到瀏覽器返回的響應(yīng)是:ERR_INVALID_HTTP_RESPONSE,發(fā)送的響應(yīng)無效。
為什么?這是因為NIOServer中的輸出格式HTTP協(xié)議不認(rèn)識。
實(shí)現(xiàn)HTTP服務(wù)器
所以如果使用Java NIO實(shí)現(xiàn)一個HTTP服務(wù)器,需要處理很多的工作,但是如果用Netty實(shí)現(xiàn)一個HTTP服務(wù)器非常簡單,直接上代碼:
Netty實(shí)現(xiàn)HTTP服務(wù)器
運(yùn)行這個示例后,你可以使用瀏覽器或者其他工具發(fā)送HTTP請求到 http://localhost:8080 ,一個HTTP服務(wù)器就誕生了,非常簡單。
示例代碼說明
接下來對代碼進(jìn)行講解:
代碼中的b.group(bossGroup, workerGroup)意思是有兩個線程組會去處理服務(wù)器中的IO事件,bossGroup只用一個線程來專門負(fù)責(zé)監(jiān)聽服務(wù)端的端口,接收客戶端連接請求,并將連接分配給 workerGroup 中的 EventLoop 進(jìn)行處理。
workerGroup負(fù)責(zé)處理已接收的連接的 I/O 事件,將請求解碼、處理業(yè)務(wù)邏輯以及發(fā)送響應(yīng)等操作都交給 EventLoop 來處理。這個是典型的主從Reactor模式,通過將連接的接收和處理分離到不同的線程池中,可以提高網(wǎng)絡(luò)應(yīng)用程序的性能,模型如下。
圖片
NioServerSocketChannel是指定服務(wù)器的Channel類型,還有NioDatagramChannel等類型,取決于應(yīng)用場景。
.handler(new LoggingHandler(LogLevel.INFO))是為bossGroup指定一個通道處理器,記錄進(jìn)出 Channel 的數(shù)據(jù)流,將相關(guān)信息打印到日志中,便于排查。
.childHandler()則是為workerGroup中的EventLoop配置處理器,比如請求解碼、處理業(yè)務(wù)邏輯以及發(fā)送響應(yīng)。
ChannelPipeline就是添加具體的通道處理器,代碼中的HttpServerCodec、HttpObjectAggregator處理器都是用來處理HTTP請求的編解碼,SimpleChannelInboundHandler則是拿到經(jīng)過多個處理器的數(shù)據(jù)流后進(jìn)行業(yè)務(wù)邏輯及響應(yīng)。
總結(jié)
Netty是一個非常優(yōu)秀的、強(qiáng)大的、高性能的網(wǎng)絡(luò)通信框架,在這個互聯(lián)網(wǎng)飛速發(fā)展的時代,我們需要了解并且使用像這樣的優(yōu)秀的框架,幫助我們快速開發(fā)應(yīng)用,在使用它的同時要知其原理,也可以在業(yè)務(wù)中進(jìn)行創(chuàng)新,就像Dubbo、gRPC、Zookeeper一樣采用Netty成為與其一樣優(yōu)秀的框架。
本文轉(zhuǎn)載自微信公眾號「Hi程序員」,可以通過以下二維碼關(guān)注。轉(zhuǎn)載本文請聯(lián)系Hi程序員公眾號。