本文首發於微信公眾號【猿燈塔】,轉載引用請說明出處
接下來的時間燈塔君持續更新Netty系列一共九篇
當前:Netty 源碼解析(一)開始
Netty 源碼解析(二): Netty 的 Channel
Netty 源碼解析(三): Netty 的 Future 和 Promise
Netty 源碼解析(四): Netty 的 ChannelPipeline
Netty 源碼解析(五): Netty 的線程池分析
Netty 源碼解析(六): Channel 的 register 操作
Netty 源碼解析(七): NioEventLoop 工作流程
Netty 源碼解析(八): 回到 Channel 的 register 操作
Netty 源碼解析(九): connect 過程和 bind 過程分析
今天呢!燈塔君跟大家講:
Netty 源碼解析(一)
前言:本文將介紹Netty,Java平台上使用最廣泛的 NIO 包,它是對JDK中的NIO實現的一層封裝,讓我們能更方便地開發NIO程序。其實,Netty 不僅僅是NIO吧,但是基本上大家都沖着NIO來的。
燈塔君感覺國內對於Netty的吹噓是有點過了,主要是很多人靠它吃飯,要么是搞培訓的,要么是出書的,恨不得把 Netty 吹上天去,這種現象也是挺不好的,反而使得初學者覺得Netty是什么高深的技術一樣。
Netty的源碼不是很簡單,因為它比較多,而且各個類之間的關系錯綜復雜,很多人說它的源碼很好,這點燈塔君覺得一般,真要說好代碼,還得Doug Lea的並發源碼比較漂亮,一行行都是精華,不過它們是不同類型的,也沒什么好對比的。
Netty源碼好就好在它的接口使用比較靈活,往往接口好用的框架,源碼都不會太簡單。
本文將立足於源碼分析,如果讀者已經對Netty有些了解,或者使用過,那就更好了。
- 本文只介紹TCP相關的內容,Netty對於其他協議的支持,不在本文的討論范圍內。
- 和並發包的源碼分析不一樣,我不可能一行一行源碼說,所以有些異常分支是會直接略過,除非我覺得需要介紹。
- Netty源碼一直在更新,各版本之間有些差異,我是按照2018-09-06的最新版本 4.1.25.Final 來進行介紹的。
建議初學者在看完本文以后,可以去翻翻《Netty In Action》,網上也可以找到中文文字版的。
一.准備
學習源碼,一開始肯定是准備環境。
燈塔君喜歡用maven,也喜歡Spring Boot,所以我一般先到https://start.spring.io/准備一個最簡單的腳手架。
10秒搞定腳手架,然后就是導入到Intellij 中,如果用新版本的Spring Boot,可能還需要等待下載依賴,期間打開https://mvnrepository.com/搜索馬上要用到的maven依賴。
Netty分為好些模塊,有netty-handler,netty-buffer、netty-transport、netty-common 等等也有一個netty-all,它包含了所有的模塊。
既然我們是源碼分析,那么自然是用一個最簡單的。netty-all不是最好的選擇,netty-example才是:
1<dependency>2 <groupId>io.netty</groupId>3 <artifactId>netty-example</artifactId>4 <version>4.1.25.Final</version>5</dependency>
它不僅可以解決我們的依賴,而且example里面的示例非常適合我們學習使用。
二.Echo例子
Netty作為NIO的庫,自然既可以作為服務端接受請求,也可以作為客戶端發起請求.使用Netty開發客戶端或服務端都是非常簡單的,Netty做了很好的封裝,我們通常只要開發一個或多個handler用來處理我們的自定義邏輯就可以了。
下面,我們來看一個經常會見到的例子,它叫Echo,也就是回聲,客戶端傳過去什么值,服務端原樣返回什么值。
開netty-example的源碼把echo包下面的代碼復制出來玩一玩。

上面的代碼基本就是模板代碼,每次使用都是這一個套路,唯一需要我們開發的部分是handler(...)和childHandler(...)方法中指定的各個handler,如EchoServerHandler和EchoClientHandler,當然Netty源碼也給我們提供了很多的handler,比如上面的 LoggingHandler,它就是Netty源碼中為我們提供的,需要的時候直接拿過來用就好了。
我們先來看一下上述代碼中涉及到的一些內容:
- ServerBootstrap類用於創建服務端實例,Bootstrap用於創建客戶端實例。
- 兩個EventLoopGroup:bossGroup和workerGroup,它們涉及的是Netty的線程模型,可以看到服務端有兩個group而客戶端只有一個,它們就是Netty中的線程池。
- Netty中Channel,沒有直接使用Java原生的ServerSocketChannel和SocketChannel,而是包裝了NioServerSocketChannel和NioSocketChannel與之對應。
當然,也有對其他協議的支持,如支持UDP協議的 NioDatagramChannel本文只關心TCP相關的。
- 左邊handler(...)方法指定了一個handler(LoggingHandler),這個handler是給服務端收到新的請求的時候處理用的,右邊handler(...)方法指定了客戶端處理請求過程中需要使用的handlers。
如果你想在EchoServer中也指定多個handler也可以像右邊的EchoClient一樣使用ChannelInitializer
- 左邊childHandler(…) 指定了childHandler,這邊的handlers是給新創建的連接用的,我們知道服務端ServerSocketChannel在accept一個連接以后,需要創建SocketChannel的實例,childHandler(…)中設置的handler就是用於處理新創建的SocketChannel的,而不是用來處理ServerSocketChannel實例的。
- pipeline:handler可以指定多個(需要上面的ChannelInitializer類輔助),它們會組成了一個 pipeline,它們其實就類似攔截器的概念,現在只要記住一點每個NioSocketChannel或NioServerSocketChannel實例內部都會有一個pipeline實例pipeline中還涉及到handler 的執行順序。
- ChannelFuture:這個涉及到Netty中的異步編程,和JDK中的Future接口類似。
對於不了解Netty的讀者,也不要有什么壓力,燈塔君會一一介紹它們,本文主要面向新手,燈塔君覺得比較難理解或比較重要的部分,會花比較大的篇幅來介紹清楚。
上面的源碼中沒有展示消息發送和消息接收的處理,此部分燈塔君會在介紹完上面的這些內容以后再進行介紹。
下面,將分塊來介紹這些內容。鑒於讀者對NIO或Netty的了解程度可能參差不齊,燈塔君為了照顧初學者很多地方需要啰嗦一些,所以希望讀者一節一節往下看,對於自己熟悉的內容可以適當看快一些,敬請期待!
365天干貨不斷,可以微信搜索「 猿燈塔」第一時間閱讀,回復【資料】【面試】【簡歷】有我准備的一線大廠面試資料和簡歷模板