Netty原理分析

来源:https://www.cnblogs.com/lfs2640666960/archive/2018/11/23/10010011.html
-Advertisement-
Play Games

作為當前最流行的NIO框架,Netty在互聯網領域、大數據分散式計算領域、游戲行業、通信行業等獲得了廣泛的應用,一些業界著名的開源組件也基於Netty的NIO框架構建。 ...


Netty是一個高性能、非同步事件驅動的NIO框架,它提供了對TCP、UDP和文件傳輸的支持,作為一個非同步NIO框架,Netty的所有IO操作都是非同步非阻塞的,通過Future-Listener機制,用戶可以方便的主動獲取或者通過通知機制獲得IO操作結果。

作為當前最流行的NIO框架,Netty在互聯網領域、大數據分散式計算領域、游戲行業、通信行業等獲得了廣泛的應用,一些業界著名的開源組件也基於Netty的NIO框架構建。

Netty架構分析

Netty 採用了比較典型的三層網路架構進行設計,邏輯架構圖如下所示:

第一層:Reactor 通信調度層,它由一系列輔助類完成,包括 Reactor 線程 NioEventLoop 以及其父類、NioSocketChannel/NioServerSocketChannel 以及其父類、ByteBuffer 以及由其衍生出來的各種 Buffer、Unsafe 以及其衍生出的各種內部類等。該層的主要職責就是監聽網路的讀寫和連接操作,負責將網路層的數據讀取到記憶體緩衝區中,然後觸發各種網路事件,例如連接創建、連接激活、讀事件、寫事件等等,將這些事件觸發到 PipeLine 中,由 PipeLine 充當的職責鏈來進行後續的處理。

第二層:職責鏈 PipeLine,它負責事件在職責鏈中的有序傳播,同時負責動態的編排職責鏈,職責鏈可以選擇監聽和處理自己關心的事件,它可以攔截處理和向後/向前傳播事件,不同的應用的 Handler 節點的功能也不同,通常情況下,往往會開發編解碼 Hanlder 用於消息的編解碼,它可以將外部的協議消息轉換成內部的 POJO 對象,這樣上層業務側只需要關心處理業務邏輯即可,不需要感知底層的協議差異和線程模型差異,實現了架構層面的分層隔離。

第三層:業務邏輯處理層,可以分為兩類:

1.純粹的業務邏輯處理,例如訂單處理。

2.應用層協議管理,例如HTTP協議、FTP協議等。

接下來,我從影響通信性能的三個方面(I/O模型、線程調度模型、序列化方式)來談談Netty的架構。

IO模型

Netty的I/O模型基於非阻塞I/O實現,底層依賴的是JDK NIO框架的Selector。

Selector提供選擇已經就緒的任務的能力。簡單來講,Selector會不斷地輪詢註冊在其上的Channel,如果某個Channel上面有新的TCP連接接入、讀和寫事件,這個Channel就處於就緒狀態,會被Selector輪詢出來,然後通過SelectionKey可以獲取就緒Channel的集合,進行後續的I/O操作。

線程調度模型

常用的Reactor線程模型有三種,分別如下:

1.Reactor單線程模型:Reactor單線程模型,指的是所有的I/O操作都在同一個NIO線程上面完成。對於一些小容量應用場景,可以使用單線程模型。

2.Reactor多線程模型:Rector多線程模型與單線程模型最大的區別就是有一組NIO線程處理I/O操作。主要用於高併發、大業務量場景。

3.主從Reactor多線程模型:主從Reactor線程模型的特點是服務端用於接收客戶端連接的不再是個1個單獨的NIO線程,而是一個獨立的NIO線程池。利用主從NIO線程模型,可以解決1個服務端監聽線程無法有效處理所有客戶端連接的性能不足問題。

序列化方式

影響序列化性能的關鍵因素總結如下:

1.序列化後的碼流大小(網路帶寬占用)

2.序列化&反序列化的性能(CPU資源占用)

3.併發調用的性能表現:穩定性、線性增長、偶現的時延毛刺等

鏈路有效性檢測

心跳檢測機制分為三個層面:

1.TCP層面的心跳檢測,即TCP的Keep-Alive機制,它的作用域是整個TCP協議棧;

2.協議層的心跳檢測,主要存在於長連接協議中。例如SMPP協議;

3.應用層的心跳檢測,它主要由各業務產品通過約定方式定時給對方發送心跳消息實現。

心跳檢測的目的就是確認當前鏈路可用,對方活著並且能夠正常接收和發送消息。作為高可靠的NIO框架,Netty也提供了基於鏈路空閑的心跳檢測機制:

1.讀空閑,鏈路持續時間t沒有讀取到任何消息;

2.寫空閑,鏈路持續時間t沒有發送任何消息;

3.讀寫空閑,鏈路持續時間t沒有接收或者發送任何消息。

零拷貝

“零拷貝”是指電腦操作的過程中, CPU不需要為數據在記憶體之間的拷貝消耗資源 。而它通常是指電腦在網路上發送文件時,不需要將文件內容拷貝到用戶空間(User Space)而  直接在內核空間(Kernel Space)中傳輸到網路的方式

Netty的“零拷貝”主要體現在三個方面

Netty的 接收和發送ByteBuffer採用DIRECT BUFFERS,使用堆外直接記憶體進行Socket讀寫,不需要進行位元組緩衝區的二次拷貝 。如果使用傳統的堆記憶體(HEAP BUFFERS)進行Socket讀寫,JVM會將堆記憶體Buffer拷貝一份到直接記憶體中,然後才寫入Socket中。相比於堆外直接記憶體,消息在發送過程中多了一次緩衝區的記憶體拷貝

讀取直接從“堆外直接記憶體”,不像傳統的堆記憶體和直接記憶體拷貝

ByteBufAllocator 通過ioBuffer分配堆外記憶體

Netty提供了 組合Buffer對象 ,可以聚合多個ByteBuffer對象,用戶可以  像操作一個Buffer那樣方便的對組合Buffer進行操作 ,避免了傳統通過記憶體拷貝的方式將幾個小Buffer合併成一個大的Buffer

Netty允許我們將多段數據合併為一整段虛擬數據供用戶使用,而過程中不需要對數據進行拷貝操作

組合Buffer對象,避免了記憶體拷貝

ChannelBuffer介面:Netty為需要傳輸的數據制定了統一的ChannelBuffer介面

·       使用getByte(int index)方法來實現隨機訪問

·       使用雙指針的方式實現順序訪問

·       Netty主要實現了HeapChannelBuffer,ByteBufferBackedChannelBuffer,與Zero Copy直接相關的CompositeChannelBuffer類

CompositeChannelBuffer類

CompositeChannelBuffer類的作用是將多個ChannelBuffer組成一個虛擬的ChannelBuffer來進行操作

為什麼說是虛擬的呢,因為CompositeChannelBuffer並沒有將多個ChannelBuffer真正的組合起來,而只是保存了他們的引用,這樣就避免了數據的拷貝,實現了Zero Copy,內部實現

其中readerIndex既讀指針和writerIndex既寫指針是從AbstractChannelBuffer繼承而來的

components是一個ChannelBuffer的數組,他保存了組成這個虛擬Buffer的所有子Buffer

indices是一個int類型的數組,它保存的是各個Buffer的索引值

lastAccessedComponentId是一個int值,它記錄了最後一次訪問時的子Buffer ID

CompositeChannelBuffer實際上就是將一系列的Buffer通過數組保存起來,然後實現了ChannelBuffer 的介面,使得在上層看來,操作這些Buffer就像是操作一個單獨的Buffer一樣

Netty的文件傳輸採用了 transferTo方法 ,它可以直接將文件緩衝區的數據發送到目標Channel,避免了傳統通過迴圈write方式導致的記憶體拷貝問題

Linux中的sendfile()以及Java NIO中的FileChannel.transferTo()方法都實現了零拷貝的功能,而在Netty中也通過在FileRegion中包裝了NIO的FileChannel.transferTo()方法實現了零拷貝

Netty 的 Zero-copy 體現在如下幾個個方面:

l  Netty 提供了 CompositeByteBuf 類, 它可以將多個 ByteBuf 合併為一個邏輯上的 ByteBuf, 避免了各個 ByteBuf 之間的拷貝。

l  通過 wrap 操作, 我們可以將byte[] 數組、ByteBuf、ByteBuffer等包裝成一個 Netty ByteBuf 對象, 進而避免了拷貝操作。

l  ByteBuf 支持 slice 操作,因此可以將 ByteBuf 分解為多個共用同一個存儲區域的ByteBuf, 避免了記憶體的拷貝。

l  通過 FileRegion 包裝的FileChannel.tranferTo 實現文件傳輸, 可以直接將文件緩衝區的數據發送到目標 Channel, 避免了傳統通過迴圈 write 方式導致的記憶體拷貝問題。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 前端開發過程中,少不了自己封裝一些通用的包,但又不想放在公共的平臺,所以搭建一個npm私有的倉庫是很有必要的。 在這裡簡單介紹如何使用 verdoccio 在docker環境下的配置。verdoccio,輕量級私有npm代理註冊表。加上docker,那就真的無敵方便了,搭建一個私有倉庫輕輕鬆松幾分鐘 ...
  • "策略模式原文地址" "更多《設計模式系列教程》" "更多免費教程" 0. 項目地址 作者按:《每天一個設計模式》旨在初步領會設計模式的精髓,目前採用 ( 靠這吃飯 )和 ( 純粹喜歡 )兩種語言實現。誠然,每種設計模式都有多種實現方式,但此小冊只記錄最直截了當的實現方式 :) "本節課代碼" "《 ...
  • 無狀態登錄原理 1.1.什麼是有狀態? 有狀態服務,即服務端需要記錄每次會話的客戶端信息,從而識別客戶端身份,根據用戶身份進行請求的處理,典型的設計如tomcat中的session。 例如登錄:用戶登錄後,我們把登錄者的信息保存在服務端session中,並且給用戶一個cookie值,記錄對應的ses ...
  • 內置函數 絕對值函數 x=100的絕對值為:100 y= 20的絕對值為:20 求最大值、最小值、求和函數 (1, 2, 3, 4)中最大max的元素為:4 (1, 2, 3, 4)中最小min的元素為:1 (1, 2, 3, 4)中最元素累加和sum為:10 模塊中的函數 char_set長度36 ...
  • Python基礎知識(11):高級特性 一、分片(切片) 通過索引來獲取一定範圍內的元素 二、迭代 給定一個元組或列表,通過for迴圈遍歷,這種遍歷稱為迭代 結果: Alice 通過collections模塊的Iterator判斷一個對象是否是可迭代對象 enumerate函數可以把一個list變成 ...
  • [TOC] 1. static概括 當在定義類的時候,類中都會有相應的屬性和方法。而屬性和方法都是通過創建本類對象調用的。當在調用對象的某個方法時,這個方法沒有訪問到對象的特有數據時, 方法創建這個對象有些多餘 ,我們可以通過static關鍵字來實現。static它是靜態修飾符,一般用來修飾類中的成 ...
  • 1.什麼是粘包 寫在前面:只有TCP有粘包現象,UDP永遠不會粘包 1.TCP下的粘包 因為TCP協議是面向連接、面向流的,收發兩端(客戶端和伺服器端)都要有成對的socket,因此,發送端為了將多個發往接收端的包,更有效的發到對方,使用了優化方法(Nagle演算法),將多次間隔較小且數據量小的數據, ...
  • 前面介紹了數值包裝類型,因為不管是整數還是小數,它們的運算操作都是類似的,所以只要學會了Integer的用法,其它數值包裝類型即可一併掌握。但是對於布爾類型boolean來說,該類型定義的是“true”和“false”的布爾值,並非123之類的數字,因此還需專門的包裝類型Boolean來包裝bool ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...