Netty將Java NIO介面封裝,提供了全非同步程式設計方式,是各大Java專案的網路應用開發必備神器。
在本文中,將Netty學習者諮詢的相關問題,進行了歸納和總結,以問題案例做牽引,通過對案例進行剖析,講解問題背後的原理,並結合Netty原始碼分析,讓讀者能夠真正掌握Netty,在實際工作中少犯錯。
本文中的案例涵蓋了Netty 的啟動和停止、記憶體、並行多執行緒、效能、可靠性、安全等方面,囊括了Netty絕大多數常用的功能及容易讓人犯錯的地方。在案例的分析過程中,還穿插講解了Netty的問題定位思路、方法、技巧,以及解決問題使用的相關工具,對讀者在實際工作中用好Netty具有很大的幫助和啟發作用。
本文將從前言、目錄、主要內容包括的章節、專家推薦和適合本文讀者四部分內容給大家進行介紹,希望大家能仔細閱讀,理解其中的真諦,真真正正的掌握Netty這門技術,希望大家能夠喜歡!!有興趣深度學習獲取的朋友,請留意文末。
本章通過兩個簡單的案例分析,引出了號誌、Java Daemon 執行緒及Netty 優雅退出相關知識。在實際專案中,知識往往是交叉在一起的,要想熟練掌握Netty伺服器端的啟動和退出,編寫更優雅和健壯的程式碼,需要重點掌握如下幾個知識點:
(1)作業系統的號誌和JavaDeamon執行緒工作機制。
(2) Netty 的NioEventLoop執行緒工作原理。
(3) Netty 優雅退出相關的幾個核心類庫。
本章分析了一個生產環境Netty使用者端連線池資源洩漏案例,詳細講解了Netty 使用者端建立的流程和工作原理,以及在實際專案中如何正確地實現連線池,避免發生並行安全和資源不當釋放等問題。
Netty記憶體池是一把雙刃劍,使用得當會在很大程度上提升系統的效能,但是誤用則會帶來記憶體漏失問題。從表面上看,只要遵循主動申請和釋放原則即可,但是由於記憶體的申請和釋放可能由Netty框架隱性完成,增加了記憶體管理的複雜性。
通過學習Netty 收發訊息的ByteBuf 申請和釋放機制,可以避免在專案中因誤用ByteBuf而發生記憶體漏失。在熟悉了ByteBuf的申請和釋放機制後,通過對Netty記憶體池工作原理和關鍵原始碼的分析,讀者可以更好地掌握Netty記憶體池的使用方法。
ByteBuf的申請和釋放可能會跨Netty 的NioEventLoop 和業務執行緒,跨執行緒操作ByteBuf時一定要謹慎,防止發生並行安全和非法參照問題。另外,由於ByteBuf 的實現類非常多,不同的實現功能特性存在差異,使用者在使用時一定要認真閱讀API Doc 說明,必要時要看原始碼,防止誤用導致出現功能和效能問題。
本章通過傳送佇列積壓案例,對Netty的訊息傳送原理和原始碼進行了深入講解,熟悉了Netty 的傳送佇列工作機制、高低水位機制等,就可以在實際專案中更好地利用這些功能,提升基於Netty構建的通訊框架的可靠性。
對於高並行接入的API閘道器類產品,需要謹慎處理訊息的記憶體申請和釋放,減少不必要的申請(例如透傳類場景),同時要防止記憶體空間的浪費。借鑑Netty請求訊息讀取的記憶體申請策略和動態擴容機制,並用在實際專案中,可以得到較大的效能提升。
ChannelHandler是使用者最常用的介面,掌握了ChannelHandler 及ChannelPipeline 工作原理,就清楚了什麼時候該使用共用的ChannelHandler,什麼時候該對ChannelHandler做並行保護。無論缺少保護還是過度保護,都會給業務帶來副作用,甚至嚴重的功能或效能問題,因此ChannelHandler的並行安全性是非常重要的。
當Netty伺服器端接收不到訊息時,首先需要檢查是使用者端沒有傳送到伺服器端,還是伺服器端沒有讀取訊息。導致伺服器端無法讀取訊息的原因有很多,常見的包括GC導致的應用執行緒暫停、伺服器端的NioEventLoop執行緒被意外阻塞等。通過網路I/O執行緒和業務邏輯執行緒分離,可以實現雙方的並行處理,提升系統的可靠性。對於使用者而言,在編寫程式碼時,始終需要考慮NioEventLoop執行緒是否會被業務程式碼阻塞,只有消除所有可能導致的阻塞點,才能保證程式穩定執行。
就Netty而言,掌握執行緒模型的重要性不亞於熟練使用它的API和功能。很多時候業務遇到的功能、效能等問題,都是由於缺乏對Netty執行緒模型和原理的理解導致的。對Netty的版本升級需要從功能、相容性和效能等多個角度進行綜合考慮,切不可只盯著API和功能變更這個「芝麻」,而丟掉了執行緒模型和效能這個「西瓜」。API的變更會導致編譯錯誤,但是效能下降卻隱藏於無形之中,稍不留意就會中招。對於強調快速交付和敏捷開發的網際網路類應用,升級的時候尤其要小心,不能功能調通後簡單驗證就匆忙,上線。
Netty框架本身實現了高效能的網路讀寫操作,但是後端業務邏輯執行卻是影響效能的關鍵要素,如果直接將複雜的業務邏輯操作放在I/O執行緒中完成,一些同步阻塞操作可能會導致I/O執行緒被阻塞。當把業務邏輯單獨拆分到業務執行緒池中進行處理,與I/0執行緒隔離時,不同的業務執行緒模型對效能的影響也非常大。Netty 提供了預設的並行排程ChannelHandler的能力,但是如果使用不當,也會帶來效能問題。對於業務自定義實現的執行緒池,如果追求更高的效能,就需要在消除或者減輕鎖競爭上下工夫,執行緒繫結技術是一個不錯的選擇,但是也需要根據業務實際場景來實現,例如TCP長連線就可以使用Channelld做Key,如果是短連線,使用者端的埠是隨機變化的,則不適合使用Channelld。
除了通過作業系統核心引數、Netty框架和JVM調優來提升單節點處理效能,還可以通過分散式叢集的方式提升整個伺服器端的處理能力,把效能的壓力分散到各個節點上。除了可以降低單個節點的風險,也可以利用雲平臺的彈性伸縮實現伺服器端的快速擴容,以應對突發的流量洪峰。如果每個節點負擔過重,一旦某個節點宕機,流量會瞬間轉移到其他節點,導致其他節點超負荷執行,系統的可靠性降低。通過「分散式+彈性伸縮」構建可平滑擴容的IoT伺服器端,是未來的一.種主流模式。
靜態檢查本來是為了提升程式碼品質,但是由於盲目按照工具的建議做修改,對業務執行態的關鍵程式碼路徑及上下文場景都不清楚,最終導致了嚴重的效能問題。由於Netty通常被用於高效能的通訊框架,所以任何涉及效能的修改一定要謹慎,修改之後需要結合業務場景做相應的效能測試,以驗證修改是否合理。
當我們對服務呼叫時延進行精細化分析時,需要把Netty通訊框架底層的處理耗時資料也採集並進行分析,由於Netty的I/O操作都是非同步的,因此不能像傳統同步呼叫那樣做效能資料統計,需要註冊效能統計監聽器,在非同步回撥中完成計數。另外,Netty 的1/0執行緒池、訊息傳送佇列等實現比較特殊,與傳統的Tomcat等框架實現策略不同,因此Netty的關鍵效能資料採集不能照搬JDK和Tomcat的做法。
Netty 4.1 提供了完整的HTTP/2協定棧,使用者可以基於Netty 4.1 框架快速開發支援HTTP/2的伺服器端應用。通過學習Netty HTTP/2協定棧在gRPC中的應用,可以掌握HTTP/2使用者端和伺服器端的建立、HTTP/2訊息的收發及序列化和反序列化等功能,學習和借鑑gRPC HTTP/2處理的優點,可以在實際專案中少走很多彎路。
在通常情況下,在做功能測試或者並行壓力不大時,HTTP請求訊息可以一次性接收完成,此時ChannelHandler的channelReadComplete方法會被呼叫一次,但是當一個整包訊息經過多次讀取才能完成解碼時,channelReadComplete方法就會被呼叫多次。如果業務的功能正確性依賴channelReadComplete方法的呼叫次數,當用戶端並行壓力大或者採用chunked 編碼時,功能就會出錯。因此,需要熟悉和掌握Netty 的事件觸發機制及ChannelHandler的呼叫策略,這樣才能防止在生產環境中「踩坑」。
流量整形與流控的最大區別在於,流控會拒絕訊息,流量整形不拒絕和丟棄訊息,無論接收量多大,它總能以近似恆定的速度下發訊息,跟變壓器的原理和功能類似。
當存在跨網路邊界的RPC呼叫時,往往需要通過TLS/SSL對傳輸通道進行加密,以防止請求和響應訊息中的敏感資料洩露。通過Netty提供的SslHandler可以方便地實現單向和雙向認證,對於有較高效能訴求的場景,可以使用OpenSSL引擎來提升SSL/TLS的通訊效能。
隨著資訊保安和個人隱私資料保護的加強,越來越多的RPC框架開始支援SSL/TLS傳輸通道加密,表面上增加資料加解密功能只對系統的效能有一些影響,但實際上系統的可靠性也會面臨比較大的挑戰,特別是高並行、低時延類的業務,一.旦發生批次服務呼叫超時,就會導致大量的SSL鏈路重建,在業務高峰期,如果伺服器端可靠性設計欠缺,很有可能宕機,導致業務中斷。
針對HTTPS服務的優化,除了功能上加強可靠性設計,更需要從架構層面做系統性的優化,借鑑gRPC的設計理念,基於HTTP/2構建非同步流式RPC呼叫是個不錯的選擇。
可靠性設計的關鍵在於對非預期異常場景的保護,應用層協定棧會考慮應用協定異常時通訊雙方應該怎麼正確處理異常,但是對於那些不遵循協定規範實現的使用者端,協定規範是無法強制約束對方的,特別是在物聯網應用中,面對各種廠家的不同終端裝置接入,伺服器端需要應對各種異常。只有可靠性做得足夠好,MQTT服務才能更從容地應對海量裝置的接入。
在實際專案中僅僅會用Netty是遠遠不夠的,由於Netty承擔了RPC呼叫工作,一旦發生問題會導致RPC或者微服務呼叫失敗,由此引起的業務中斷後果很嚴重。除了實踐,需要熟練掌握Netty的核心類庫和關鍵排程流程,這樣才能得心應手地解決各種問題。
這份【Netty進階之路:跟著案例學Netty】 共有346頁,需要完整版的朋友,可以轉發此文並關注小編,檢視下方圖片,掃碼新增,或私信小編【學習】來獲取!!
本文適合架構師、設計師、開發工程師、測試工程師,以及對Java NIO框架、Netty感興趣的其他相關人士閱讀。
希望大家能夠仔細揣摩本文的所有內容,爭取都能夠完全掌握甚至精通,這樣子不至於在今後的社會中處於劣勢狀態,永遠走在前面,也希望大家能夠推陳出新,形成自己的一套知識框架。
大家加油努力學習吧!!