本書(shū)循序漸進(jìn)地介紹Netty各個(gè)方面的內(nèi)容。本書(shū)共分為4個(gè)部分:第一部分介紹Netty的相關(guān)概念以及核心組件,第二部分介紹自定義協(xié)議經(jīng)常用到的編解碼器,第三部分們介紹Netty對(duì)于應(yīng)用層高級(jí)協(xié)議的支持,覆蓋常見(jiàn)的協(xié)議及其在實(shí)踐中的應(yīng)用,第四部分是幾個(gè)案例研究。此外,附錄部分還簡(jiǎn)單地介紹Maven,以及如何通過(guò)使用Maven編譯和運(yùn)行本書(shū)中的示例。
- Netty之父”Trustin Lee作序推薦
- 阿里巴巴中間件高級(jí)技術(shù)專家為本書(shū)中文版作序推薦
- 系統(tǒng)而詳細(xì)地介紹了Netty的各個(gè)方面并附帶了即用型的優(yōu)質(zhì)示例
- 附帶行業(yè)一線公司的案例研究
- 極實(shí)用的Netty技術(shù)書(shū)
無(wú)論是構(gòu)建高性能的Web、游戲服務(wù)器、推送系統(tǒng)、RPC框架、消息中間件還是分布式大數(shù)據(jù)處理引擎,都離不開(kāi)Netty,在整個(gè)行業(yè)中,Netty廣泛而成功的應(yīng)用,使其成為了Java高性能網(wǎng)絡(luò)編程的卓絕框架。
Netty的現(xiàn)Tech Lead Norman在本書(shū)中循序漸進(jìn)地講解了Netty的各個(gè)關(guān)鍵部分,在看完本書(shū)后,你不但可以熟練地使用Netty來(lái)構(gòu)建以上系統(tǒng),并且還可以避免很多常見(jiàn)的陷阱。
無(wú)論是想要學(xué)習(xí)Spring 5 、Spark、Cassandra等這樣的系統(tǒng),還是通過(guò)學(xué)習(xí)Netty來(lái)構(gòu)建自己的基于Java的高性能網(wǎng)絡(luò)框架,或者是更加具體的高性能Web或者游戲服務(wù)器等,本書(shū)都將是你的超強(qiáng)拍檔。
本書(shū)中文版基于Netty4.1.9做了修訂,希望本書(shū)能夠給你帶來(lái)一個(gè)接近完美的閱讀體驗(yàn),并能幫到你。
前言
回首過(guò)去,我仍然不敢相信我做到了。
當(dāng)我從2011年年末開(kāi)始為Netty 做貢獻(xiàn)時(shí),我怎么也想不到我會(huì)寫一本關(guān)于Netty 的書(shū),并且成為該框架本身的核心開(kāi)發(fā)者之一。
這一切都始于我在2009 年參與的Apache James 項(xiàng)目,一個(gè)在Apache 軟件基金會(huì)下開(kāi)發(fā)的基于Java 的郵件服務(wù)器。
像許多應(yīng)用程序一樣,Apache James 需要構(gòu)建在一個(gè)堅(jiān)實(shí)的網(wǎng)絡(luò)抽象之上。在考察提供網(wǎng)絡(luò)抽象的項(xiàng)目領(lǐng)域時(shí),我偶然地發(fā)現(xiàn)了Netty,并且立即就愛(ài)上了它。在我從用戶的角度更加地熟悉了Netty 之后,我便開(kāi)始轉(zhuǎn)向改進(jìn)它和回饋社區(qū)。
盡管我第一次貢獻(xiàn)的范圍有限,但是很快變得明顯的是,進(jìn)行貢獻(xiàn)以及和社區(qū)進(jìn)行相關(guān)問(wèn)題的討論,尤其是和項(xiàng)目的創(chuàng)始人Trustin Lee,對(duì)于我的個(gè)人成長(zhǎng)非常有益。這樣的經(jīng)驗(yàn)牢牢地吸引了我,我喜歡將我的空閑時(shí)間更多地投入到社區(qū)中。我在郵件列表上提供幫助,并且加入了IRC頻道的討論。致力于Netty 開(kāi)始是一種愛(ài)好,但很快就演變成了一種激情。
我對(duì)Netty 的激情最終導(dǎo)致我在Red Hat 就業(yè)。這簡(jiǎn)直是美夢(mèng)成真,因?yàn)镽ed Hat 雇傭我來(lái)致力于我所熱愛(ài)的項(xiàng)目。我最終知道了Claus Ibsen 在那時(shí)正(現(xiàn)在仍然)致力于Apache Camel。Claus 和我認(rèn)識(shí)到,雖然Netty 擁有堅(jiān)實(shí)的用戶基礎(chǔ)以及良好的JavaDoc,但是它缺乏一個(gè)更加高級(jí)別的文檔。Claus 是《Camel in Action》(Manning,2010)的作者,他給了我為Netty 寫一本類似的書(shū)的想法。關(guān)于這個(gè)想法,我考慮了幾個(gè)星期,最終接受了。這也就有了本書(shū)。
在編寫本書(shū)的過(guò)程中,我也越來(lái)越多地參與到了社區(qū)中。伴隨著超過(guò)1000 次的提交①,我最終成為了僅次于Trustin Lee 的最活躍的貢獻(xiàn)者。我經(jīng)常在世界各地的各種會(huì)議以及技術(shù)聚會(huì)上演講Netty。最終Netty 開(kāi)啟了另一個(gè)在蘋果公司的就業(yè)機(jī)會(huì),我目前在云基礎(chǔ)設(shè)施工程團(tuán)隊(duì)(Cloud Infrastructure Engineering Team)擔(dān)任資深軟件工程師。我繼續(xù)致力于Netty,并且經(jīng)常貢獻(xiàn)回饋社區(qū),同時(shí)也幫助推動(dòng)該項(xiàng)目。
Norman Maurer
蘋果公司云基礎(chǔ)設(shè)施工程
我在馬薩諸塞州韋斯頓的Harvard Pilgrim Health Care 擔(dān)任Dell Services 的顧問(wèn)時(shí),就主要側(cè)重于構(gòu)建可復(fù)用的基礎(chǔ)設(shè)施組件。我們的目標(biāo)是找到這樣一種擴(kuò)展通用代碼庫(kù)的方式:它不僅對(duì)通常軟件過(guò)程有利,而且還能將應(yīng)用程序開(kāi)發(fā)者從編寫既麻煩又平凡的管道代碼(plumbingcode)責(zé)任中解脫出來(lái)。
我一度發(fā)現(xiàn),有兩個(gè)相關(guān)的項(xiàng)目都在使用一個(gè)第三方的理賠處理系統(tǒng),該系統(tǒng)只支持直接的CP/IP 通信。其中一個(gè)項(xiàng)目需要使用Java 重新實(shí)現(xiàn)一個(gè)文檔不太詳細(xì)的構(gòu)建在供應(yīng)商的專有的基于分隔的格式上的遺留COBAL 模塊。這個(gè)模塊最終被另一個(gè)項(xiàng)目取代了,那個(gè)項(xiàng)目將使用較新的基于XML的接口來(lái)連接到該相同理賠系統(tǒng)上。(但是使用的仍然是裸套接字,而不是SOAP!)在我看來(lái),這是一個(gè)理想的開(kāi)發(fā)一個(gè)通用API 的機(jī)會(huì),而且也充滿了樂(lè)趣。我知道將會(huì)有嚴(yán)格的吞吐量和可靠性要求,并且設(shè)計(jì)也仍然在不斷地演進(jìn)。顯然,為了支持快速的迭代周期,底層的網(wǎng)絡(luò)代碼必須完全和業(yè)務(wù)邏輯解耦。
我對(duì)于Java 的高性能網(wǎng)絡(luò)編程框架的調(diào)研把我直接帶到了Netty 面前。(在第1 章開(kāi)頭讀者會(huì)讀到一個(gè)假設(shè)的項(xiàng)目,它其實(shí)基本上取材自現(xiàn)實(shí)生活。)我很快就確信了Netty 的方式,使用可動(dòng)態(tài)配置的編碼器和解碼器,能夠完美地滿足我們的需求:兩個(gè)項(xiàng)目將可以使用相同的API,并部署所使用的特定數(shù)據(jù)格式所需的處理器。在我發(fā)現(xiàn)該供應(yīng)商的產(chǎn)品也是基于Netty 的之后,我變得更加堅(jiān)信了!
就在那時(shí),我得知有一本我一直都在期待的叫《Netty 實(shí)戰(zhàn)》的書(shū)正在編寫中。我讀了早期的草稿,并帶著一些問(wèn)題和建議很快和Norman 取得了聯(lián)系。在我們多次的交流過(guò)程中,我們常常會(huì)談到要記住最終用戶的視角,而且因?yàn)槲耶?dāng)時(shí)正在參與一個(gè)實(shí)實(shí)在在的Netty 項(xiàng)目,所以我很高興地?fù)?dān)當(dāng)了這個(gè)(合著者/最終用戶)角色。
我希望,通過(guò)這種方式,我們能夠成功地滿足開(kāi)發(fā)者們的需求。如果您有任何關(guān)于我們?nèi)绾文軌蚴沟帽緯?shū)變得更加有用的建議,請(qǐng)?jiān)趆ttps://forums.manning.com/forums/netty-in-action 聯(lián)系我們。
Marvin Allen Wolfthal
Dell Services
Norman Maurer,是蘋果公司的資深軟件工程師,同時(shí)也是Netty的核心開(kāi)發(fā)人員。
Marvin Allen Wolfthal,是Dell Services的顧問(wèn),他使用Netty實(shí)現(xiàn)了多個(gè)任務(wù)關(guān)鍵型的企業(yè)系統(tǒng)。
何品,目前是淘寶的一名資深軟件工程師,熱愛(ài)網(wǎng)絡(luò)、并發(fā)、異步相關(guān)的主題以及函數(shù)式編程,同時(shí)也是Netty、Akka等項(xiàng)目的貢獻(xiàn)者,活躍于Scala社區(qū),目前也在從事GraphQL相關(guān)的開(kāi)發(fā)工作。
第一部分 Netty的概念及體系結(jié)構(gòu)
第1 章 Netty——異步和事件驅(qū)動(dòng) 3
1.1 Java 網(wǎng)絡(luò)編程 4
1.1.1 Java NIO 5
1.1.2 選擇器 6
1.2 Netty 簡(jiǎn)介 6
1.2.1 誰(shuí)在使用Netty 7
1.2.2 異步和事件驅(qū)動(dòng) 8
1.3 Netty 的核心組件 9
1.3.1 Channel 9
1.3.2 回調(diào) 9
1.3.3 Future 10
1.3.4 事件和ChannelHandler 11
1.3.5 把它們放在一起 12
1.4 小結(jié) 13
第2 章 你的第一款Netty應(yīng)用程序 14
2.1 設(shè)置開(kāi)發(fā)環(huán)境 14
2.1.1 獲取并安裝Java 開(kāi)發(fā)工具包 14
2.1.2 下載并安裝IDE 15
2.1.3 下載和安裝Apache Maven 15
2.1.4 配置工具集 16
2.2 Netty 客戶端/服務(wù)器概覽 16
2.3 編寫Echo 服務(wù)器 17
2.3.1 ChannelHandler 和業(yè)務(wù)邏輯 17
2.3.2 引導(dǎo)服務(wù)器 18
2.4 編寫Echo 客戶端 21
2.4.1 通過(guò)ChannelHandler 實(shí)現(xiàn)客戶端邏輯 21
2.4.2 引導(dǎo)客戶端 22
2.5 構(gòu)建和運(yùn)行Echo 服務(wù)器和客戶端 24
2.5.1 運(yùn)行構(gòu)建 24
2.5.2 運(yùn)行Echo 服務(wù)器和客戶端 27
2.6 小結(jié) 29
第3 章 Netty 的組件和設(shè)計(jì) 30
3.1 Channel、EventLoop 和ChannelFuture 30
3.1.1 Channel 接口 31
3.1.2 EventLoop 接口 31
3.1.3 ChannelFuture 接口 32
3.2 ChannelHandler 和ChannelPipeline 32
3.2.1 ChannelHandler 接口 32
3.2.2 ChannelPipeline 接口 33
3.2.3 更加深入地了解ChannelHandler 34
3.2.4 編碼器和解碼器 35
3.2.5 抽象類SimpleChannelInboundHandler 35
3.3 引導(dǎo) 36
3.4 小結(jié) 37
第4 章 傳輸 38
4.1 案例研究:傳輸遷移 38
4.1.1 不通過(guò)Netty 使用OIO和NIO 39
4.1.2 通過(guò)Netty 使用OIO和NIO 41
4.1.3 非阻塞的Netty 版本 42
4.2 傳輸API 43
4.3 內(nèi)置的傳輸 45
4.3.1 NIO——非阻塞I/O 46
4.3.2 Epoll——用于Linux的本地非阻塞傳輸 47
4.3.3 OIO——舊的阻塞I/O 48
4.3.4 用于JVM 內(nèi)部通信的Local 傳輸 48
4.3.5 Embedded 傳輸 49
4.4 傳輸?shù)挠美?49
4.5 小結(jié) 51
第5 章 ByteBuf 52
5.1 ByteBuf 的API 52
5.2 ByteBuf 類——Netty的數(shù)據(jù)容器 53
5.2.1 它是如何工作的 53
5.2.2 ByteBuf 的使用模式 53
5.3 字節(jié)級(jí)操作 57
5.3.1 隨機(jī)訪問(wèn)索引 57
5.3.2 順序訪問(wèn)索引 57
5.3.3 可丟棄字節(jié) 58
5.3.4 可讀字節(jié) 58
5.3.5 可寫字節(jié) 59
5.3.6 索引管理 59
5.3.7 查找操作 60
5.3.8 派生緩沖區(qū) 60
5.3.9 讀/寫操作 62
5.3.10 更多的操作 64
5.4 ByteBufHolder 接口 65
5.5 ByteBuf 分配 65
5.5.1 按需分配:ByteBufAllocator 接口 65
5.5.2 Unpooled 緩沖區(qū) 67
5.5.3 ByteBufUtil 類 67
5.6 引用計(jì)數(shù) 67
5.7 小結(jié) 68
第6 章 ChannelHandler 和ChannelPipeline 70
6.1 ChannelHandler 家族 70
6.1.1 Channel 的生命周期 70
6.1.2 ChannelHandler的生命周期 71
6.1.3 ChannelInboundHandler接口 71
6.1.4 ChannelOutboundHandler接口 73
6.1.5 ChannelHandler 適配器 74
6.1.6 資源管理 74
6.2 ChannelPipeline 接口 76
6.2.1 修改ChannelPipeline 78
6.2.2 觸發(fā)事件 79
6.3 ChannelHandlerContext接口 80
6.3.1 使用ChannelHandlerContext 82
6.3.2 ChannelHandler 和ChannelHandlerContext 的高級(jí)用法 84
6.4 異常處理 86
6.4.1 處理入站異常 86
6.4.2 處理出站異常 87
6.5 小結(jié) 88
第7 章 EventLoop 和線程模型 89
7.1 線程模型概述 89
7.2 EventLoop 接口 90
7.2.1 Netty 4 中的I/O 和事件處理 92
7.2.2 Netty 3 中的I/O 操作 92
7.3 任務(wù)調(diào)度 93
7.3.1 JDK 的任務(wù)調(diào)度API 93
7.3.2 使用EventLoop調(diào)度任務(wù) 94
7.4 實(shí)現(xiàn)細(xì)節(jié) 95
7.4.1 線程管理 95
7.4.2 EventLoop/線程的分配 96
7.5 小結(jié) 98
第8 章 引導(dǎo) 99
8.1 Bootstrap 類 99
8.2 引導(dǎo)客戶端和無(wú)連接協(xié)議 101
8.2.1 引導(dǎo)客戶端 102
8.2.2 Channel 和EventLoopGroup 的兼容性 103
8.3 引導(dǎo)服務(wù)器 104
8.3.1 ServerBootstrap 類 104
8.3.2 引導(dǎo)服務(wù)器 105
8.4 從Channel引導(dǎo)客戶端 107
8.5 在引導(dǎo)過(guò)程中添加多個(gè)ChannelHandler 108
8.6 使用Netty 的ChannelOption 和屬性 110
8.7 引導(dǎo)DatagramChannel 111
8.8 關(guān)閉 112
8.9 小結(jié) 112
第9 章 單元測(cè)試 113
9.1 EmbeddedChannel概述 113
9.2 使用EmbeddedChannel測(cè)試ChannelHandler 115
9.2.1 測(cè)試入站消息 115
9.2.2 測(cè)試出站消息 118
9.3 測(cè)試異常處理 119
9.4 小結(jié) 121
第二部分 編解碼器
第10 章 編解碼器框架 125
10.1 什么是編解碼器 125
10.2 解碼器 125
10.2.1 抽象類ByteToMessageDecoder 126
10.2.2 抽象類ReplayingDecoder 127
10.2.3 抽象類MessageToMessageDecoder 128
10.2.4 TooLongFrameException 類 130
10.3 編碼器 131
10.3.1 抽象類MessageToByteEncoder 131
10.3.2 抽象類MessageToMessageEncoder 132
10.4 抽象的編解碼器類 133
10.4.1 抽象類ByteToMessageCodec 133
10.4.2 抽象類MessageToMessageCodec 134
10.4.3 CombinedChannelDuplexHandler 類 137
10.5 小結(jié) 138
第11 章 預(yù)置的ChannelHandler和編解碼器 139
11.1 通過(guò)SSL/TLS 保護(hù)Netty 應(yīng)用程序 139
11.2 構(gòu)建基于Netty 的HTTP/HTTPS 應(yīng)用程序 141
11.2.1 HTTP 解碼器、編碼器和編解碼器 141
11.2.2 聚合HTTP 消息 143
11.2.3 HTTP 壓縮 144
11.2.4 使用HTTPS 145
11.2.5 WebSocket 146
11.3 空閑的連接和超時(shí) 148
11.4 解碼基于分隔符的協(xié)議和基于長(zhǎng)度的協(xié)議 150
11.4.1 基于分隔符的協(xié)議 150
11.4.2 基于長(zhǎng)度的協(xié)議 153
11.5 寫大型數(shù)據(jù) 155
11.6 序列化數(shù)據(jù) 1 57
11.6.1 JDK 序列化 157
11.6.2 使用JBoss Marshalling進(jìn)行序列化 157
11.6.3 通過(guò)Protocol Buffers序列化 159
11.7 小結(jié) 160
第三部分 網(wǎng)絡(luò)協(xié)議
第12 章 WebSocket 163
12.1 WebSocket 簡(jiǎn)介 163
12.2 我們的WebSocket 示例應(yīng)用程序 164
12.3 添加WebSocket支持 165
12.3.1 處理HTTP 請(qǐng)求 165
12.3.2 處理WebSocket 幀 168
12.3.3 初始化ChannelPipeline 169
12.3.4 引導(dǎo) 171
12.4 測(cè)試該應(yīng)用程序 173
12.5 小結(jié) 176
第13章 使用UDP 廣播事件 177
13.1 UDP 的基礎(chǔ)知識(shí) 177
13.2 UDP 廣播 178
13.3 UDP 示例應(yīng)用程序 178
13.4 消息 POJO:LogEvent 179
13.5 編寫廣播者 180
13.6 編寫監(jiān)視器 185
13.7 運(yùn)行LogEventBroadcaster 和LogEventMonitor 187
13.8 小結(jié) 189
第四部分 案例研究
第14 章 案例研究,第一部分 193
14.1 Droplr—構(gòu)建移動(dòng)服務(wù) 193
14.1.1 這一切的起因 193
14.1.2 Droplr 是怎樣工作的 194
14.1.3 創(chuàng)造一個(gè)更加快速的上傳體驗(yàn) 194
14.1.4 技術(shù)棧 196
14.1.5 性能 199
14.1.6 小結(jié)——站在巨人的肩膀上 200
14.2 Firebase—實(shí)時(shí)的數(shù)據(jù)同步服務(wù) 200
14.2.1 Firebase 的架構(gòu) 201
14.2.2 長(zhǎng)輪詢 201
14.2.3 HTTP 1.1 keep-alive和流水線化 204
14.2.4 控制SslHandler 205
14.2.5 Firebase 小結(jié) 207
14.3 Urban Airship—構(gòu)建移動(dòng)服務(wù) 207
14.3.1 移動(dòng)消息的基礎(chǔ)知識(shí) 207
14.3.2 第三方遞交 208
14.3.3 使用二進(jìn)制協(xié)議的例子 209
14.3.4 直接面向設(shè)備的遞交 211
14.3.5 Netty 擅長(zhǎng)管理大量的并發(fā)連接 212
14.3.6 Urban Airship 小結(jié)——跨越防火墻邊界 213
14.4 小結(jié) 214
第15 章 案例研究,第二部分 215
15.1 Netty 在Facebook 的使用:Nifty 和Swift 215
15.1.1 什么是Thrift 215
15.1.2 使用Netty 改善Java Thrift 的現(xiàn)狀 216
15.1.3 Nifty 服務(wù)器的設(shè)計(jì) 217
15.1.4 Nifty 異步客戶端的設(shè)計(jì) 220
15.1.5 Swift:一種更快的構(gòu)建Java Thrift 服務(wù)的方式 221
15.1.6 結(jié)果 221
15.1.7 Facebook 小結(jié) 224
15.2 Netty 在Twitter的使用:Finagle 224
15.2.1 Twitter 成長(zhǎng)的煩惱 224
15.2.2 Finagle 的誕生 224
15.2.3 Finagle 是如何工作的 225
15.2.4 Finagle 的抽象 230
15.2.5 故障管理 231
15.2.6 組合服務(wù) 232
15.2.7 未來(lái):Netty 232
15.2.8 Twitter 小結(jié) 233
15.3 小結(jié) 233
附錄 Maven 介紹 234