關于我們
書單推薦
新書推薦
|
Netty權威指南(第2版)
《Netty quanwei指南(第2 版)》是異步非阻塞通信領域的經典之作,基于全新版本的Netty 5.0 編寫,是國內首本深入介紹Netty 原理和架構的書籍,也是作者多年實戰(zhàn)經驗的總結和濃縮。內容不僅包含Java NIO入門知識、Netty 的基礎功能開發(fā)指導、編解碼框架定制等,還包括私有協(xié)議棧定制和開發(fā)、Netty 核心類庫源碼分析,以及Netty 的架構剖析。
1、Hadoop、Storm、Spark、Facebook、Twitter、阿里巴巴都在使用Java高性能NIO通信框架Netty,本書告訴你Why,通過本書你可以全面、系統(tǒng)地理解Netty 架構設計理念,以及異步NIO 編程。
2、本書作者為資深一線專家,在產品中廣泛應用了Netty等NIO框架,具有豐富的多年實踐經驗,這就使得本書內容帶有很強的實踐性,讓你更全面快速掌握Java高并發(fā)異步通信的優(yōu)選框架Netty的用法。 3、本書第一版出版后受到業(yè)界的一致好評,應讀者的要求,第2版增加了MessagePack 編解碼、服務端創(chuàng)建、客戶端創(chuàng)建、高性能之道、可靠性、安全性等內容,內容更精彩。 Netty是什么?使用Netty能夠做什么?為什么要從傳統(tǒng)的Socket開發(fā)切換到NIO進行編程?為什么不直接基于JDK的NIO類庫編程而選擇Netty?如何全面系統(tǒng)地掌握Netty進行NettyNIO開發(fā)、Netty編解碼開發(fā)、Netty多協(xié)議開發(fā)?如何通過對Netty源碼的學習獲得更深入地知識?掌握了Netty后,如何將其應用到實際架構中?Netty工程師的就業(yè)前景和可涉足的行業(yè)是怎樣的?本書都會一一解答。 推薦購買:
2014 年6 月《Netty 權威指南》第1 版面世之后,很多讀者通過郵件等方式向我表達了對本書的喜愛和贊譽。同時,對本書的一些瑕疵和不足也進行了指正,并給出了合理的建議。我對讀者反饋的合理建議進行了記錄和總結,以期在未來修訂版或者第2 版中能夠修正這些問題。
大約在2014 年11 月份的時候,編輯與我協(xié)商出版《Netty 權威指南(第2 版)》的事宜,考慮到如下幾個因素,最終我決定推出第2 版: ◎ 第一版需要修正少部分印刷不太清晰的圖片,這會改變后續(xù)章節(jié)的頁碼; ◎ 源碼分析章節(jié)的代碼希望重新編排一下,與前面的開發(fā)示例保持一致; ◎ 部分章節(jié)和內容需要優(yōu)化調整; ◎ 部分讀者對推出第2 版的要求。 第2 版的主要變更如下,刪除第1 版中的如下章節(jié): ◎ 第7 章:Java 序列化; ◎ 第12 章:UDP 協(xié)議開發(fā); ◎ 第13 章:文件傳輸; ◎ 第22 章:Netty 行業(yè)應用。 新增本書中的如下章節(jié): ◎ 第7 章:MessagePack 編解碼; ◎ 第13 章:服務端創(chuàng)建; ◎ 第14 章:客戶端創(chuàng)建; ◎ 第22 章:高性能之道; ◎ 第23 章:可靠性; ◎ 第24 章:安全性。 第1 版最初的想法是盡量照顧NIO 編程和Netty 初學者,因此入門和基礎功能使用示例占了很大比例,涵蓋的范圍也很廣。但事實上,由于Netty 的功能過于龐雜,一本書很難涵蓋Netty 的所有功能點,因此,刪除了不太常用的Java 序列化、UDP 協(xié)議開發(fā)和文件傳輸。 Netty 行業(yè)應用的內容很多讀者都很期望,希望能夠展開詳細講解一下。我思索再三,忍痛割愛,不僅沒有加強本章節(jié),反而刪除了它。為什么呢?對于真正想了解行業(yè)應用的讀者,需要展開詳細講解才能夠講透,剖開Netty 在Spark、Hadoop 等大數據領域的應用不談,即便是作為分布式服務框架的內部高性能通信組件,例如Dubbo,沒有大篇幅也很難講透,與其一筆概括,泛泛而談,還不如留給其他作者或者未來抽空單獨梳理。 掌握Netty 的基礎功能使用比較容易,但是理解Netty 底層的架構以及主要架構特性的設計理念卻是件困難的事情,它需要長期的行業(yè)積累以及對Netty 底層源碼的透徹理解。應廣大讀者的要求,在第2 版中新增了Netty 的高性能、安全性和可靠性的架構剖析,通過這些章節(jié)的學習,讀者可以更加清晰地理解Netty 架構設計理念。 盡管我本人已經有7 年的NIO 編程和實戰(zhàn)經驗,在產品中也廣泛應用了Netty 和Mina等NIO 框架。但是,受限于個人能力和水平,本書一定還有紕漏和不妥之處,希望廣大讀者能夠批評指正。讀者在閱讀本書或者實際工作中如果有Netty 相關的疑問,也可以直接聯(lián)系我,我會盡量回復。我的聯(lián)系方式如下: ◎ 郵箱:neu_lilinfeng@sina.com ◎ 新浪微博:Nettying ◎ 微信:Nettying。 《Netty 權威指南》第1 版出版之后,很多讀者來信咨詢自己實際工作和學習中遇到的Netty 問題和案例,有些案例和問題頗具典型性。我將這些案例進行了總結,在微信公眾號“Netty 之家”中定期推送,希望廣大讀者可以關注。 感謝博文視點的小編丁一瓊MM 和幕后的美工,正是你們的辛苦工作才保證了本書能夠順利出版;感謝華為IT PaaS 望岳、莫小君和Digital SDP 集成開發(fā)部徐皓等領導對我的信任和支持;感謝我的老婆在我編輯第2 版期間赦免了我做飯和刷碗的義務,我得以抽出時間安心寫作。 最后感謝《Netty 權威指南》第1 版的讀者,你們的理解、鼓勵和支持,使我有足夠的勇氣和動力繼續(xù)前行。希望大家攜起手來共同推動NIO 編程和Netty 在國內的應用和發(fā)展。 李林鋒 2015 年1 月27 日于南京 第1版前言 大約在2008 年的時候,我參與設計和開發(fā)的一個電信系統(tǒng)在月初出賬期,總是發(fā)生大量的連接超時和讀寫超時異常,業(yè)務的失敗率相比于平時高了很多,報表中的很多指標都差強人意。后來經過排查,發(fā)現問題主要出現在下游網元的處理性能上,月初的時候BSS 出賬,在出賬期間BSS 系統(tǒng)運行緩慢,由于雙方采用了同步阻塞式的HTTP+XML 進行通信,導致任何一方處理緩慢都會影響對方的處理性能。按照故障隔離的設計原則,對方處理速度慢或者不回應,不應該影響系統(tǒng)的其他功能模塊或者協(xié)議棧,但是在同步阻塞I/O 通信模型下,這種故障傳播和相互影響是不可避免的,很難通過業(yè)務層面解決。 受限于當時Tomcat 和Servlet 的同步阻塞I/O 模型,以及在Java 領域異步HTTP 協(xié)議棧的技術積累不足,當時我們并沒有辦法完全解決這個問題,只能通過調整線程池策略和HTTP 超時時間來從業(yè)務層面做規(guī)避。 2009 年,由于對技術的熱愛,我作為業(yè)務骨干被領導派去參加一個重點業(yè)務平臺的研發(fā)工作,與兩位資深的架構師(其中一位工作20 年,做華為交換機出身)共同參與。這是我第一次全面接觸異步I/O 編程和高性能電信級協(xié)議棧的開發(fā),眼界大開——異步高性能內部協(xié)議棧、異步HTTP、異步SOAP、異步SMPP……所有的協(xié)議棧都是異步非阻塞的。后來的性能測試表明:基于Reactor 模型統(tǒng)一調度的長連接和短連接協(xié)議棧,無論是性能、可靠性還是可維護性,都可以“秒殺”傳統(tǒng)基于BIO 開發(fā)的應用服務器和各種協(xié)議棧,這種差異本質上是一種代差。 在我從事異步NIO 編程的2009 年,業(yè)界還沒有成熟的NIO 框架,那個時候Mina 剛剛開始起步,功能和性能都達不到商用標準。最困難的是,國內Java 領域的異步通信還沒有流行,整個業(yè)界的積累都非常少。那時資料匱乏,能夠交流和探討的圈內人很少,一旦踩住“地雷”,就需要夜以繼日地維護。在隨后2 年多的時間里,經歷了十多次的在通宵、凌晨被一線的運維人員電話吵醒等種種磨難之后,我們自研的NIO 框架才逐漸穩(wěn)定和成熟。期間,解決的BUG 總計20~30 個。 從2004 年JDK 1.4 首次提供NIO 1.0 類庫到現在,已經過去了整整10 年。JSR 51 的設計初衷就是讓Java 能夠提供非阻塞、具有彈性伸縮能力的異步I/O 類庫,從而結束了Java在高性能服務器領域的不利局面。然而,在相當長的一段時間里,Java 的NIO 編程并沒有流行起來,究其原因如下。 1.大多數高性能服務器,被C 和C++語言盤踞,由于它們可以直接使用操作系統(tǒng)的 異步I/O 能力,所以對JDK 的NIO 并不關心; 2.移動互聯(lián)網尚未興起,基于Java 的大規(guī)模分布式系統(tǒng)極少,很多中小型應用服務 對于異步I/O 的訴求不是很強烈; 3.高性能、高可靠性領域,例如銀行、證券、電信等,依然以C++為主導,Java 充 當打雜的角色,NIO 暫時沒有用武之地; 4.當時主流的J2EE 服務器,幾乎全部基于同步阻塞I/O 構建,例如Servlet、Tomcat 等,由于它們應用廣泛,如果這些容器不支持NIO,用戶很難具備獨立構建異步協(xié)議棧的 能力; 5.異步NIO 編程門檻比較高,開發(fā)和維護一款基于NIO 的協(xié)議棧對很多中小型公司 來說像是一場噩夢; 6.業(yè)界NIO 框架不成熟,很難商用; 7.國內研發(fā)界對NIO 的陌生和認識不足,沒有充分重視。 基于上述幾種原因,NIO 編程的推廣和發(fā)展長期滯后。值得欣慰的是,隨著大規(guī)模分布式系統(tǒng)、大數據和流式計算框架的興起,基于Java 來構建這些系統(tǒng)已經成為主流,NIO編程和NIO 框架在此期間得到了大規(guī)模的商用。在互聯(lián)網領域,阿里的分布式服務框架Dubbo、RocketMQ,大數據的基礎序列化和通信框架Avro,以及很多開源的軟件都已經開始使用Netty 來構建高性能、分布式通信能力,Netty 社區(qū)的活躍度也名列前茅。根據目前的信息,Netty 已經在如下幾個領域得到了大規(guī)模的商業(yè)應用。 1.互聯(lián)網領域; 2.電信領域; 3.大數據領域; 4.銀行、證券等金融領域; 5.游戲行業(yè); 6.電力等企業(yè)市場。 2014 年春節(jié)前,我分享了一篇博文《Netty 5.0 架構剖析和源碼解讀》,短短1 個月下 載量達到了4000 多。很多網友向我咨詢NIO 編程技術、NIO 框架如何選擇等問題,也有一些圈內朋友和出版社邀請我寫一本關于Netty 的技術書籍。作為最流行、表現最優(yōu)異的NIO 框架,Netty 深受大家喜愛,但是長期以來除了User Guide 之外,國內鮮有Netty 相關的技術書籍供廣大NIO 編程愛好者學習和參考。由于Netty 源碼的復雜性和NIO 編程本身的技術門檻限制,對于大多數讀者而言,通過自己閱讀和分析源碼來深入掌握Netty 的設計原理和實現細節(jié)是件困難的事情。從2011 年開始我系統(tǒng)性地分析和應用了Netty 和Mina,轉瞬間已經過去了3 年多。在這3 年的時間里,我們的系統(tǒng)經受了無數嚴苛的考驗,在這個過程中,我對Netty 和Mina 有了更深刻的體驗,也積累了豐富的運維和實戰(zhàn)經驗。我們都是開源框架Netty 的受益者,為了讓更多的朋友和同行能夠了解NIO 編程,深入學習和掌握Netty 這個NIO 利器,我打算將我的經驗和大家分享,同時也結束國內尚無Netty學習教材的尷尬境地。 致謝 如果說個人能夠改變自己命運的話,對于程序員來說,唯有通過不斷地學習和實踐,努力提升自己的技能,才有可能找到更好的機會,充分發(fā)揮和體現自己的價值。我希望本書能夠為你的成功助一臂之力。 感謝博文視點的策劃編輯丁一瓊和幕后的美編,正是你們的辛苦工作才保證了本書能夠順利出版;感謝華為Netty 愛好者和關注本書的領導同事們的支持,你們的理解和鼓勵為我提供了足夠的勇氣;感謝我的家人和老婆的支持,寫書占用了我?guī)缀跛械臉I(yè)余時間,沒有你們的理解和支持,我很難安心寫作。 最后感謝Netty 中國社區(qū)的朋友,我的微博粉絲和所有喜歡Netty 的朋友們,你們對技術的熱情是鼓勵我寫書的最重要動力,沒有你們,就沒有本書。希望大家一如既往地喜歡NIO 編程,喜歡Netty,以及相互交流和分享,共同推動整個國內異步高性能通信領域的技術發(fā)展。 李林鋒 2014 年5 月11 日于南京紫軒閣
李林峰,Netty中國推廣者,現華為技術有限公司平臺中間件架構與設計部設計師,公司總裁技術創(chuàng)新獎獲得者。長期從事高性能通信軟件的架構設計和開發(fā)工作,有多年在NIO領域的設計、開發(fā)和運維經驗,精通NIO編程和Netty、Mina等主流NIO框架。
基礎篇 走進Java NIO
第1 章 Java 的I/O 演進之路......2 1.1 I/O 基礎入門......3 1.1.1 Linux 網絡I/O 模型簡介......3 1.1.2 I/O 多路復用技術......6 1.2 Java 的I/O 演進......8 1.3 總結...... 10 第2 章 NIO 入門...... 11 2.1 傳統(tǒng)的BIO 編程...... 11 2.1.1 BIO 通信模型圖...... 12 2.1.2 同步阻塞式I/O 創(chuàng)建的TimeServer 源碼分析...... 13 2.1.3 同步阻塞式I/O 創(chuàng)建的TimeClient 源碼分析...... 16 2.2 偽異步I/O 編程...... 18 2.2.1 偽異步I/O 模型圖...... 19 2.2.2 偽異步I/O 創(chuàng)建的TimeServer 源碼分析...... 19 2.2.3 偽異步I/O 弊端分析...... 21 2.3 NIO 編程...... 24 2.3.1 NIO 類庫簡介...... 24 2.3.2 NIO 服務端序列圖...... 28 2.3.3 NIO 創(chuàng)建的TimeServer 源碼分析...... 30 2.3.4 NIO 客戶端序列圖...... 36 2.3.5 NIO 創(chuàng)建的TimeClient 源碼分析...... 39 2.4 AIO 編程...... 45 2.4.1 AIO 創(chuàng)建的TimeServer 源碼分析...... 46 2.4.2 AIO 創(chuàng)建的TimeClient 源碼分析...... 51 2.4.3 AIO 版本時間服務器運行結果...... 56 2.5 4 種I/O 的對比...... 58 2.5.1 概念澄清...... 58 2.5.2 不同I/O 模型對比...... 59 2.6 選擇Netty 的理由...... 60 2.6.1 不選擇Java 原生NIO 編程的原因...... 61 2.6.2 為什么選擇Netty ...... 62 2.7 總結...... 63 入門篇 Netty NIO 開發(fā)指南 第3 章 Netty 入門應用...... 66 3.1 Netty 開發(fā)環(huán)境的搭建...... 66 3.1.1 下載Netty 的軟件包...... 67 3.1.2 搭建Netty 應用工程...... 67 3.2 Netty 服務端開發(fā)...... 68 3.3 Netty 客戶端開發(fā)...... 73 3.4 運行和調試...... 76 3.4.1 服務端和客戶端的運行...... 76 3.4.2 打包和部署...... 77 3.5 總結...... 77 第4 章 TCP 粘包/拆包問題的解決之道...... 79 4.1 TCP 粘包/拆包...... 79 4.1.1 TCP 粘包/拆包問題說明...... 80 4.1.2 TCP 粘包/拆包發(fā)生的原因...... 80 4.1.3 粘包問題的解決策略...... 81 4.2 未考慮TCP 粘包導致功能異常案例...... 82 4.2.1 TimeServer 的改造...... 82 4.2.2 TimeClient 的改造...... 83 4.2.3 運行結果...... 84 4.3 利用LineBasedFrameDecoder 解決TCP 粘包問題...... 85 4.3.1 支持TCP 粘包的TimeServer ...... 86 4.3.2 支持TCP 粘包的TimeClient...... 88 4.3.3 運行支持TCP 粘包的時間服務器程序...... 90 4.3.4 LineBasedFrameDecoder 和StringDecoder 的原理分析...... 91 4.4 總結...... 92 第5 章 分隔符和定長解碼器的應用...... 93 5.1 DelimiterBasedFrameDecoder 應用開發(fā)...... 94 5.1.1 DelimiterBasedFrameDecoder 服務端開發(fā)...... 94 5.1.2 DelimiterBasedFrameDecoder 客戶端開發(fā)...... 97 5.1.3 運行DelimiterBasedFrameDecoder 服務端和客戶端...... 99 5.2 FixedLengthFrameDecoder 應用開發(fā)...... 101 5.2.1 FixedLengthFrameDecoder 服務端開發(fā)...... 101 5.2.2 利用telnet 命令行測試EchoServer 服務端...... 103 5.3 總結...... 104 中級篇 Netty 編解碼開發(fā)指南 第6 章 編解碼技術...... 106 6.1 Java 序列化的缺點...... 107 6.1.1 法跨語言...... 107 6.1.2 序列化后的碼流太大...... 107 6.1.3 序列化性能太低...... 110 6.2 業(yè)界主流的編解碼框架...... 113 6.2.1 Google 的Protobuf 介紹...... 113 6.2.2 Facebook 的Thrift 介紹...... 115 6.2.3 JBoss Marshalling 介紹...... 116 6.3 總結...... 117 第7 章 MessagePack 編解碼...... 118 7.1 MessagePack 介紹...... 118 7.1.1 MessagePack 多語言支持...... 119 7.1.2 MessagePack Java API 介紹...... 119 7.1.3 MessagePack 開發(fā)包下載...... 120 7.2 MessagePack 編碼器和解碼器開發(fā)...... 120 7.2.1 MessagePack 編碼器開發(fā)...... 120 7.2.2 MessagePack 解碼器開發(fā)...... 121 7.2.3 功能測試...... 121 7.3 粘包/半包支持...... 124 7.4 總結...... 127 第8 章 Google Protobuf 編解碼...... 128 8.1 Protobuf 的入門...... 129 8.1.1 Protobuf 開發(fā)環(huán)境搭建...... 129 8.1.2 Protobuf 編解碼開發(fā)...... 131 8.1.3 運行Protobuf 例程...... 133 8.2 Netty 的Protobuf 服務端開發(fā)...... 133 8.2.1 Protobuf 版本的圖書訂購服務端開發(fā)...... 134 8.2.2 Protobuf 版本的圖書訂購客戶端開發(fā)...... 136 8.2.3 Protobuf 版本的圖書訂購程序功能測試...... 139 8.3 Protobuf 的使用注意事項...... 140 8.4 總結...... 142 第9 章 JBoss Marshalling 編解碼...... 143 9.1 Marshalling 開發(fā)環(huán)境準備...... 143 9.2 Netty 的Marshalling 服務端開發(fā)...... 144 9.3 Netty 的Marshalling 客戶端開發(fā)...... 147 9.4 運行Marshalling 客戶端和服務端例程...... 149 9.5 總結...... 150 高級篇 Netty 多協(xié)議開發(fā)和應用 第10 章 HTTP 協(xié)議開發(fā)應用...... 154 10.1 HTTP 協(xié)議介紹...... 155 10.1.1 HTTP 協(xié)議的URL ...... 155 10.1.2 HTTP 請求消息(HttpRequest)...... 155 10.1.3 HTTP 響應消息(HttpResponse) ...... 158 10.2 Netty HTTP 服務端入門開發(fā)...... 159 10.2.1 HTTP 服務端例程場景描述...... 160 10.2.2 HTTP 服務端開發(fā)...... 160 10.2.3 Netty HTTP 文件服務器例程運行結果...... 166 10.3 Netty HTTP+XML 協(xié)議棧開發(fā)...... 170 10.3.1 開發(fā)場景介紹...... 171 10.3.2 HTTP+XML 協(xié)議棧設計...... 174 10.3.3 高效的XML 綁定框架JiBx ...... 175 10.3.4 HTTP+XML 編解碼框架開發(fā)...... 183 10.3.5 HTTP+XML 協(xié)議棧測試...... 199 10.3.6 小結...... 201 10.4 總結...... 202 第11 章 WebSocket 協(xié)議開發(fā)...... 203 11.1 HTTP 協(xié)議的弊端...... 204 11.2 WebSocket 入門...... 204 11.2.1 WebSocket 背景...... 205 11.2.2 WebSocket 連接建立...... 206 11.2.3 WebSocket 生命周期...... 207 11.2.4 WebSocket 連接關閉...... 208 11.3 Netty WebSocket 協(xié)議開發(fā)...... 209 11.3.1 WebSocket 服務端功能介紹...... 209 11.3.2 WebSocket 服務端開發(fā)...... 210 11.3.3 運行WebSocket 服務端...... 218 11.4 總結...... 219 第12 章 私有協(xié)議棧開發(fā)...... 221 12.1 私有協(xié)議介紹...... 221 12.2 Netty 協(xié)議棧功能設計...... 223 12.2.1 網絡拓撲圖...... 223 12.2.2 協(xié)議棧功能描述...... 224 12.2.3 通信模型...... 224 12.2.4 消息定義...... 225 12.2.5 Netty 協(xié)議支持的字段類型...... 226 12.2.6 Netty 協(xié)議的編解碼規(guī)范...... 227 12.2.7 鏈路的建立...... 229 12.2.8 鏈路的關閉...... 230 12.2.9 可靠性設計...... 230 12.2.10 安全性設計...... 232 12.2.11 可擴展性設計...... 232 12.3 Netty 協(xié)議棧開發(fā)...... 233 12.3.1 數據結構定義...... 233 12.3.2 消息編解碼...... 237 12.3.3 握手和安全認證...... 241 12.3.4 心跳檢測機制...... 245 12.3.5 斷連重連...... 248 12.3.6 客戶端代碼...... 249 12.3.7 服務端代碼...... 251 12.4 運行協(xié)議棧...... 252 12.4.1 正常場景...... 252 12.4.2 異常場景:服務端宕機重啟...... 253 12.4.3 異常場景:客戶端宕機重啟...... 256 12.5 總結...... 256 第13 章 服務端創(chuàng)建...... 258 13.1 原生NIO 類庫的復雜性...... 259 13.2 Netty 服務端創(chuàng)建源碼分析...... 259 13.2.1 Netty 服務端創(chuàng)建時序圖...... 260 13.2.2 Netty 服務端創(chuàng)建源碼分析...... 263 13.3 客戶端接入源碼分析...... 272 13.4 總結...... 275 第14 章 客戶端創(chuàng)建...... 276 14.1 Netty 客戶端創(chuàng)建流程分析...... 276 14.2.1 Netty 客戶端創(chuàng)建時序圖...... 276 14.2.2 Netty 客戶端創(chuàng)建流程分析...... 277 14.2 Netty 客戶端創(chuàng)建源碼分析...... 278 14.2.1 客戶端連接輔助類Bootstrap...... 278 14.2.2 客戶端連接操作...... 281 14.2.3 異步連接結果通知...... 283 14.2.4 客戶端連接超時機制...... 284 14.3 總結...... 286 源碼分析篇 Netty 功能介紹和源碼分析 第15 章 ByteBuf 和相關輔助類...... 288 15.1 ByteBuf 功能說明...... 288 15.1.1 ByteBuf 的工作原理...... 289 15.1.2 ByteBuf 的功能介紹...... 294 15.2 ByteBuf 源碼分析...... 308 15.2.1 ByteBuf 的主要類繼承關系...... 309 15.2.2 AbstractByteBuf 源碼分析...... 310 15.2.3 AbstractReferenceCountedByteBuf 源碼分析...... 319 15.2.4 UnpooledHeapByteBuf 源碼分析...... 321 15.2.5 PooledByteBuf 內存池原理分析...... 326 15.2.6 PooledDirectByteBuf 源碼分析...... 329 15.3 ByteBuf 相關的輔助類功能介紹...... 332 15.3.1 ByteBufHolder...... 332 15.3.2 ByteBufAllocator ...... 333 15.3.3 CompositeByteBuf ...... 334 15.3.4 ByteBufUtil ...... 336 15.4 總結...... 337 第16 章 Channel 和Unsafe ...... 338 16.1 Channel 功能說明...... 338 16.1.1 Channel 的工作原理...... 339 16.1.2 Channel 的功能介紹...... 340 16.2 Channel 源碼分析...... 343 16.2.1 Channel 的主要繼承關系類圖...... 343 16.2.2 AbstractChannel 源碼分析...... 344 16.2.3 AbstractNioChannel 源碼分析...... 347 16.2.4 AbstractNioByteChannel 源碼分析...... 350 16.2.5 AbstractNioMessageChannel 源碼分析...... 353 16.2.6 AbstractNioMessageServerChannel 源碼分析...... 354 16.2.7 NioServerSocketChannel 源碼分析...... 355 16.2.8 NioSocketChannel 源碼分析...... 358 16.3 Unsafe 功能說明...... 364 16.4 Unsafe 源碼分析...... 365 16.4.1 Unsafe 繼承關系類圖...... 365 16.4.2 AbstractUnsafe 源碼分析...... 366 16.4.3 AbstractNioUnsafe 源碼分析...... 375 16.4.4 NioByteUnsafe 源碼分析...... 379 16.5 總結...... 387 第17 章 ChannelPipeline 和ChannelHandler...... 388 17.1 ChannelPipeline 功能說明...... 389 17.1.1 ChannelPipeline 的事件處理...... 389 17.1.2 自定義攔截器...... 391 17.1.3 構建pipeline ...... 392 17.1.4 ChannelPipeline 的主要特性...... 393 17.2 ChannelPipeline 源碼分析...... 393 17.2.1 ChannelPipeline 的類繼承關系圖...... 393 17.2.2 ChannelPipeline 對ChannelHandler 的管理...... 393 17.2.3 ChannelPipeline 的inbound 事件...... 396 17.2.4 ChannelPipeline 的outbound 事件...... 397 17.3 ChannelHandler 功能說明...... 398 17.3.1 ChannelHandlerAdapter 功能說明...... 399 17.3.2 ByteToMessageDecoder 功能說明...... 399 17.3.3 MessageToMessageDecoder 功能說明...... 400 17.3.4 LengthFieldBasedFrameDecoder 功能說明...... 400 17.3.5 MessageToByteEncoder 功能說明...... 404 17.3.6 MessageToMessageEncoder 功能說明...... 404 17.3.7 LengthFieldPrepender 功能說明...... 405 17.4 ChannelHandler 源碼分析...... 406 17.4.1 ChannelHandler 的類繼承關系圖...... 406 17.4.2 ByteToMessageDecoder 源碼分析...... 407 17.4.3 MessageToMessageDecoder 源碼分析...... 410 17.4.4 LengthFieldBasedFrameDecoder 源碼分析...... 411 17.4.5 MessageToByteEncoder 源碼分析...... 415 17.4.6 MessageToMessageEncoder 源碼分析...... 416 17.4.7 LengthFieldPrepender 源碼分析...... 417 17.5 總結...... 418 第18 章 EventLoop 和EventLoopGroup...... 419 18.1 Netty 的線程模型...... 419 18.1.1 Reactor 單線程模型...... 420 18.1.2 Reactor 多線程模型...... 421 18.1.3 主從Reactor 多線程模型...... 422 18.1.4 Netty 的線程模型...... 423 18.1.5 最佳實踐...... 424 18.2 NioEventLoop 源碼分析...... 425 18.2.1 NioEventLoop 設計原理...... 425 18.2.2 NioEventLoop 繼承關系類圖...... 426 18.2.3 NioEventLoop...... 427 18.3 總結...... 436 第19 章 Future 和Promise ...... 438 19.1 Future 功能...... 438 19.2 ChannelFuture 源碼分析...... 443 19.3 Promise 功能介紹...... 445 19.4 Promise 源碼分析...... 447 19.4.1 Promise 繼承關系圖...... 447 19.4.2 DefaultPromise ...... 447 19.5 總結...... 449 架構和行業(yè)應用篇 Netty 高級特性 第20 章 Netty 架構剖析...... 452 20.1 Netty 邏輯架構...... 452 20.1.1 Reactor 通信調度層...... 453 20.1.2 職責鏈ChannelPipeline ...... 453 20.1.3 業(yè)務邏輯編排層(Service ChannelHandler)...... 454 20.2 關鍵架構質量屬性...... 454 20.2.1 高性能...... 454 20.2.2 可靠性...... 457 20.2.3 可定制性...... 460 20.2.4 可擴展性...... 460 20.3 總結...... 460 第21 章 Java 多線程編程在Netty 中的應用...... 461 21.1 Java 內存模型與多線程編程...... 461 21.1.1 硬件的發(fā)展和多任務處理...... 461 21.1.2 Java 內存模型...... 462 21.2 Netty 的并發(fā)編程實踐...... 464 21.2.1 對共享的可變數據進行正確的同步...... 464 21.2.2 正確使用鎖...... 465 21.2.3 volatile 的正確使用...... 467 21.2.4 CAS 指令和原子類...... 470 21.2.5 線程安全類的應用...... 472 21.2.6 讀寫鎖的應用...... 476 21.2.7 線程安全性文檔說明...... 477 21.2.8 不要依賴線程優(yōu)先級...... 478 21.3 總結...... 479 第22 章 高性能之道...... 480 22.1 RPC 調用性能模型分析...... 480 22.1.1 傳統(tǒng)RPC 調用性能差的三宗罪...... 480 22.1.2 I/O 通信性能三原則...... 481 22.2 Netty 高性能之道...... 482 22.2.1 異步非阻塞通信...... 482 22.2.2 高效的Reactor 線程模型...... 482 22.2.3 鎖化的串行設計...... 485 22.2.4 高效的并發(fā)編程...... 486 22.2.5 高性能的序列化框架...... 486 22.2.6 零拷貝...... 487 22.2.7 內存池...... 491 22.2.8 靈活的TCP 參數配置能力...... 494 22.3 主流NIO 框架性能對比...... 495 22.4 總結...... 497 第23 章 可靠性...... 498 23.1 可靠性需求...... 498 23.1.1 宕機的代價...... 498 23.1.2 Netty 可靠性需求...... 499 23.2 Netty 高可靠性設計...... 500 23.2.1 網絡通信類故障...... 500 23.2.2 鏈路的有效性檢測...... 507 23.2.3 Reactor 線程的保護...... 510 23.2.4 內存保護...... 513 23.2.5 流量整形...... 516 23.2.6 優(yōu)雅停機接口...... 519 23.3 優(yōu)化建議...... 520 23.3.1 發(fā)送隊列容量上限控制...... 520 23.3.2 回推發(fā)送失敗的消息...... 521 23.4 總結...... 521 第24 章 安全性...... 522 24.1 嚴峻的安全形勢...... 522 24.1.1 OpenSSL Heart bleed 漏洞...... 522 24.1.2 安全漏洞的代價...... 523 24.1.3 Netty 面臨的安全風險...... 523 24.2 Netty SSL 安全特性...... 525 24.2.1 SSL 單向認證...... 525 24.2.2 SSL 雙向認證...... 532 24.2.3 第三方CA 認證...... 536 24.3 Netty SSL 源碼分析...... 538 24.3.1 客戶端...... 538 24.3.2 服務端...... 541 24.3.3 消息讀。 544 24.3.4 消息發(fā)送...... 545 24.4 Netty 擴展的安全特性...... 546 24.4.1 IP 地址黑名單機制...... 547 24.4.2 接入認證...... 548 24.4 總結...... 550 第25 章 Netty 未來展望...... 551 25.1 應用范圍...... 551 25.2 技術演進...... 552 25.3 社區(qū)活躍度...... 552 25.4 Road Map ...... 552 25.5 總結...... 553 附錄A Netty 參數配置表...... 554
13.2.1Netty服務端創(chuàng)建時序圖
下面我們對Netty服務端創(chuàng)建的關鍵步驟和原理進行講解。 步驟1:創(chuàng)建ServerBootstrap實例。ServerBootstrap是Netty服務端的啟動輔助類,它提供了一系列的方法用于設置服務端啟動相關的參數。底層通過門面模式對各種能力進行抽象和封裝,盡量不需要用戶跟過多的底層API打交道,降低用戶的開發(fā)難度。 我們在創(chuàng)建ServerBootstrap實例時,會驚訝地發(fā)現ServerBootstrap只有一個無參的構造函數,作為啟動輔助類這讓人不可思議,因為它需要與多個其他組件或者類交互。ServerBootstrap構造函數沒有參數的根本原因是因為它的參數太多了,而且未來也可能會發(fā)生變化,為了解決這個問題,就需要引入Builder模式!禘ffective Java》第二版第2條建議遇到多個構造器參數時要考慮用構建器,關于多個參數構造函數的缺點和使用構建器的優(yōu)點大家可以查閱《Effective Java》,在此不再詳述。 步驟2:設置并綁定Reactor線程池。Netty的Reactor線程池是EventLoopGroup,它實際就是EventLoop的數組。EventLoop的職責是處理所有注冊到本線程多路復用器Selector上的Channel,Selector的輪詢操作由綁定的EventLoop線程run方法驅動,在一個循環(huán)體內循環(huán)執(zhí)行。值得說明的是,EventLoop的職責不僅僅是處理網絡I/O事件,用戶自定義的Task和定時任務Task也統(tǒng)一由EventLoop負責處理,這樣線程模型就實現了統(tǒng)一。從調度層面看,也不存在在EventLoop線程中再啟動其他類型的線程用于異步執(zhí)行另外的任務,這樣就避免了多線程并發(fā)操作和鎖競爭,提升了I/O線程的處理和調度性能。 步驟3:設置并綁定服務端Channel。作為NIO服務端,需要創(chuàng)建ServerSocketChannel,Netty對原生的NIO類庫進行了封裝,對應實現是NioServerSocketChannel。對于用戶而言,不需要關心服務端Channel的底層實現細節(jié)和工作原理,只需要指定具體使用哪種服務端Channel即可。因此,Netty的ServerBootstrap方法提供了channel方法用于指定服務端Channel的類型。Netty通過工廠類,利用反射創(chuàng)建NioServerSocketChannel對象。由于服務端監(jiān)聽端口往往只需要在系統(tǒng)啟動時才會調用,因此反射對性能的影響并不大。相關代碼如下。 public ServerBootstrap channel(Class channelClass) { if (channelClass == null) { throw new NullPointerException("channelClass"); } return channelFactory(new ServerBootstrapChannelFactory(channelClass)); } 步驟4:鏈路建立的時候創(chuàng)建并初始化ChannelPipeline。ChannelPipeline并不是NIO服務端必需的,它本質就是一個負責處理網絡事件的職責鏈,負責管理和執(zhí)行ChannelHandler。網絡事件以事件流的形式在ChannelPipeline中流轉,由ChannelPipeline根據ChannelHandler的執(zhí)行策略調度ChannelHandler的執(zhí)行。典型的網絡事件如下。 。1)鏈路注冊; 。2)鏈路激活; 。3)鏈路斷開; (4)接收到請求消息; (5)請求消息接收并處理完畢; 。6)發(fā)送應答消息; 。7)鏈路發(fā)生異常; 。8)發(fā)生用戶自定義事件。 步驟5:初始化ChannelPipeline完成之后,添加并設置ChannelHandler。ChannelHandler是Netty提供給用戶定制和擴展的關鍵接口。利用ChannelHandler用戶可以完成大多數的功能定制,例如消息編解碼、心跳、安全認證、TSL/SSL認證、流量控制和流量整形等。Netty同時也提供了大量的系統(tǒng)ChannelHandler供用戶使用,比較實用的系統(tǒng)ChannelHandler總結如下。 。1)系統(tǒng)編解碼框架——ByteToMessageCodec; 。2)通用基于長度的半包解碼器——LengthFieldBasedFrameDecoder; (3)碼流日志打印Handler——LoggingHandler; 。4)SSL安全認證Handler——SslHandler; 。5)鏈路空閑檢測Handler——IdleStateHandler; 。6)流量整形Handler——ChannelTrafficShapingHandler; 。7)Base64編解碼——Base64Decoder和Base64Encoder。 創(chuàng)建和添加ChannelHandler的代碼示例如下。 .childHandler(new ChannelInitializer() { @Override public void initChannel(SocketChannel ch) throws Exception { ch.pipeline().addLast( new EchoServerHandler()); } }); 步驟6:綁定并啟動監(jiān)聽端口。在綁定監(jiān)聽端口之前系統(tǒng)會做一系列的初始化和檢測工作,完成之后,會啟動監(jiān)聽端口,并將ServerSocketChannel注冊到Selector上監(jiān)聽客戶端連接,相關代碼如下。 protected void doBind(SocketAddress localAddress) throws Exception { javaChannel().socket().bind(localAddress, config.getBacklog()); } 步驟7:Selector輪詢。由Reactor線程NioEventLoop負責調度和執(zhí)行Selector輪詢操作,選擇準備就緒的Channel集合,相關代碼如下。 private void select() throws IOException { Selector selector = this.selector; try { //此處代碼省略...... int selectedKeys = selector.select(timeoutMillis); selectCnt ++; //此處代碼省略...... } 步驟8:當輪詢到準備就緒的Channel之后,就由Reactor線程NioEventLoop執(zhí)行ChannelPipeline的相應方法,最終調度并執(zhí)行ChannelHandler,接口如圖13-2所示。 步驟9:執(zhí)行Netty系統(tǒng)ChannelHandler和用戶添加定制的ChannelHandler。ChannelPipeline根據網絡事件的類型,調度并執(zhí)行ChannelHandler,相關代碼如下。 public ChannelHandlerContext fireChannelRead(Object msg) { DefaultChannelHandlerContext next = findContextInbound(MASK_CHANNEL_READ); next.invoker.invokeChannelRead(next, msg); return this; ……
你還可能感興趣
我要評論
|