Netty如何實現高性能?
性能是設計出來的,不是測試出來的。Netty採用以下設計實現高性能:數據庫
- 採用異步非阻塞的I/O類庫,基於Reactor模式實現,解決了傳統同步阻塞I/O模式下一個服務端沒法平滑處理線性增加的客戶端的問題
- TCP接收和發送緩衝區使用直接內存代替堆內存,避免了內存複製,提高了I/O讀取和寫入的性能
- 支持經過內存池的方式循環利用ByteBuf,避免了頻繁建立和銷燬ByteBuf帶來的性能損耗。
- 可配置的I/O線程數、TCP參數等,爲不一樣的用戶場景提供定製化的調優參數,知足不一樣的性能場景
- 採用環形數組緩衝區實現無鎖化併發編程,代替傳統的線程安全容器或者鎖
- 合理使用線程安全容器、原子類等,提高系統的併發處理能力
- 關鍵資源的處理使用單線程串行化的方式,避免多線程併發訪問帶來的鎖競爭和額外的CPU資源消耗問題
- 經過引用計數器及時的申請釋放再也不被引用的對象,細粒度的內存管理下降了GC的頻率,減小了頻繁GC帶來的時延增大和CPU損耗
可靠性
做爲一個高性能的異步通訊框架,架構的可靠性是你們選擇的一個重要依據。下面咱們探討Netty架構的可靠性設計:編程
- 因爲長鏈接不須要每次發送消息都建立鏈路,也不須要在消息交互完成時關閉鏈路,所以相對於短鏈接性能更高。對於長鏈接,一旦鏈路創建成功便一直維繫雙方之間的鏈路,知道系統推出。 爲保證長鏈接的鏈路有效性,每每須要經過心跳機制週期性的進行鏈路檢測。使用週期性心跳的緣由是:在系統空閒時,例如凌晨,每每沒有業務消息。若是此時鏈路被防火牆hang住,或者遭遇網絡閃斷、網絡單通等,通訊雙方沒法識別出這類鏈路異常。等到次日業務高峯期到來時,瞬間的海量業務衝擊會致使消息積壓沒法發送給對方,因爲鏈路的重建須要時間,這期間業務大量失敗(集羣或者分佈式組網狀況會好一些)。爲了解決這個問題,須要週期性的心跳對鏈路進行有效性檢測,一旦發生問題,能夠及時關閉鏈路,重建TCP鏈接。 當有業務消息時,無需心跳檢測,能夠由業務消息進行鏈路可用性檢測。因此心跳消息每每是在鏈路空閒時發送的。 爲了支持心跳,Netty提供了以下兩種鏈路空閒檢測機制。
- 讀空閒超時機制:當連續週期T沒有消息可讀時,觸發超時Handler,用戶能夠基於讀空閒超時發送心跳消息,進行鏈路檢測;若是連續N個週期任然沒有讀取到心跳信息,能夠主動關閉鏈接。
- 寫空閒超時機制:當連續週期T沒有消息要發送時,出發超時Handler,用戶能夠基於寫空閒超時發送心跳消息,進行鏈路檢測;若是聯繫N個週期仍然沒有接收到對方的心跳消息,能夠主動關閉鏈路。 爲了知足不一樣用戶場景的心跳定製,Netty提供了空閒狀態檢測事件通知機制,用戶能夠訂閱空閒超時事件、寫空閒超時事件、讀或者寫超時事件,在接收到對應的空閒事件以後,靈活的進行定製。
- 內存保護機制 Netty提供多種機制對內存進行保護,包括如下幾個方面:
- 經過對象引用計數器對Netty的ByteBuf等內置對象進行細粒度的內存申請和釋放,對非法的對象引用進行檢測和保護。
- 經過內存池來重用ByteBuf,節省內存
- 可設置的內存容量上限,包括ByteBuf、線程池線程數等
- 優雅停機 相比於Netty的早期版本,Netty5.0版本的優雅退出功能作的更加完善。優雅停機功能指的是當系統退出時,JVM經過註冊的ShutDown Hook攔截到退出信號量,而後執行退出操做,釋放相關模塊的資源佔用,將緩衝區的消息處理完成或者清空,將待刷新的數據持久化到磁盤或者數據庫中,等到資源回收和緩衝區消息處理完成後,再退出。
可定製性
Netty的可定製性主要體如今如下幾點:數組
- 責任鏈模式:ChannelPipeline基於責任鏈模式開發,便於業務邏輯的攔截、定製和擴展。
- 基於接口的開發:關鍵的類庫都提供了接口或者抽象類,若是Netty自身的實現沒法知足用戶的需求,能夠由用戶自定義實現相關接口
- 提供了大量工廠類,經過重載這些工廠類能夠按需建立出用戶實現的對象
- 提供了大量的系統參數供用戶按需設置,加強系統的場景定製性
可擴展性
基於Netty的基礎NIO框架,能夠方便地進行應用層協議定製,例如HTTP協議棧、Thrift協議棧、FTP協議棧等。這些擴展不須要修改Netty的源碼,直接基於Netty的二進制類庫便可實現協議的擴展和定製。 目前,業界存在大量的基於Netty框架開發的協議,例如基於Netty的HTTP協議、Dubbo協議、RocketMQ內部私有協議等。安全
參考文獻:《Netty權威指南》網絡