Netty 模型理解

參考文章 1
參考文章 2

官網API文檔

在這里插入圖片描述

Reactor模型

在這里插入圖片描述

Netty模型

Netty主要基于主從Reactor多線程模型進行了一定的修改,該模型包括以下幾個組件:

  1. MainReactor(主Reactor):負責處理客戶端的連接請求。它監聽服務器上的端口,接收客戶端的連接請求,并將請求分發給SubReactor進行處理。

  2. SubReactor(從Reactor):負責處理連接成功后的通道的IO讀寫請求。每個SubReactor負責管理一組通道,它們使用多路復用技術(如Java NIO)來監聽通道上的事件,例如可讀、可寫等事件。一般情況下,每個SubReactor都對應一個線程。

  3. Worker Threads(工作線程):負責處理非IO請求,即具體的業務邏輯處理。當有非IO請求需要處理時,這些任務會被寫入一個隊列中,等待工作線程來處理。工作線程可以是線程池中的線程,也可以是其他類型的線程。
    在這里插入圖片描述

模塊組件

在這里插入圖片描述

  1. BootstrapServerBootstrap: 在Netty中,BootstrapServerBootstrap是用于啟動和配置Netty應用程序的引導類。Bootstrap類是用于客戶端程序的啟動引導類,ServerBootstrap類是服務端啟動引導類。
  2. NioEventLoopGroupNioEventLoopGroup是Netty中用于管理NioEventLoop的組件,它是一個線程池,包含多個NioEventLoop實例,它對應著主從Reactor多線程模型中ReactorNioEventLoopGroup負責創建、管理和分配NioEventLoop,處理異常情況,并提供優雅關閉的機制。它是Netty實現高性能的重要組件之一。
  3. NioEventLoopNioEventLoop是Netty中的核心組件,負責處理I/O事件和執行任務。它使用Selector來監聽和處理注冊在其上的Channel的I/O事件,同時支持異步提交和執行任務。NioEventLoop還管理定時任務和處理異常情況,是實現高性能和事件驅動的重要組成部分。

什么是Selector

  1. Selector:Netty基于Selector對象實現了I/O多路復用。通過將多個Channel注冊到一個Selector中,并使用一個線程來監聽和處理這些Channel的事件,可以高效地管理多個ChannelSelector會自動不斷地查詢這些注冊的Channel,以檢查它們是否有已就緒的I/O事件。

  2. Channel:在Netty中,Channel表示一個開放的網絡連接,可以用于讀取、寫入和處理網絡數據。它是網絡通信的基本單元,負責處理底層的數據傳輸和事件通知。

    • NioSocketChannel:異步的客戶端 TCP Socket 連接
    • NioServerSocketChannel:異步的服務器端 TCP Socket 連接
    • NioDatagramChannel:異步的 UDP 連接
    • NioSctpChannel:異步的客戶端 Sctp 連接
    • NioSctpServerChannel:異步的 Sctp 服務器端連接
  3. ChannelHandler:在Netty中,ChannelHandler是一個接口,用于處理I/O事件或攔截I/O操作,并將其轉發到ChannelPipeline中的下一個處理程序。ChannelHandler是Netty的核心組件之一,它負責處理各種事件,如連接建立、數據讀寫、異常發生等。

    • ChannelInboundHandler:用于處理入站I/O事件
    • ChannelOutboundHandler:用于處理出站I/O操作
  4. ChannelHandlerContextChannelHandlerContext保存了與特定Channel相關的所有上下文信息,同時關聯一個ChannelHandler對象,并提供了訪問ChannelChannelHandlerChannelPipeline的方法。

  5. ChannelPipline: 它是一個保存ChannelHandler的列表,用于處理或攔截Channel的入站事件和出站操作。 ChannelPipeline實現了一種高級形式的攔截過濾器模式,使用戶可以完全控制事件的處理方式以及Channel中各個的ChannelHandler如何相互交互。
    在 Netty 中每個 Channel 都有且僅有一個 ChannelPipeline 與之對應, 它們的組成關系如下:
    在這里插入圖片描述
    一個Channel包含了一個ChannelPipeline,而ChannelPipeline中維護了一個由ChannelHandlerContext組成的雙向鏈表。入站事件和出站事件在這個雙向鏈表中進行傳遞,入站事件從鏈表的head往后傳遞到最后一個入站的ChannelHandler,出站事件從鏈表的tail往前傳遞到最前一個出站的ChannelHandler,兩種類型的ChannelHandler互不干擾。通過這種設計,ChannelPipeline實現了事件的順序傳遞和處理。

  6. FutureChannelFuture: Netty中的IO操作都是異步的,這意味著在發起一個IO操作后,無需等待其完成就可以繼續執行后續的代碼邏輯。為了獲取操作的執行結果或者在操作完成時得到通知,Netty提供了FutureChannelFuture

實例代碼

服務端

public class MyServer {public static void main(String[] args) throws Exception {//創建兩個線程組 boosGroup、workerGroupEventLoopGroup bossGroup = new NioEventLoopGroup();EventLoopGroup workerGroup = new NioEventLoopGroup();try {//創建服務端的啟動對象,設置參數ServerBootstrap bootstrap = new ServerBootstrap();//設置兩個線程組boosGroup和workerGroupbootstrap.group(bossGroup, workerGroup)//設置服務端通道實現類型    .channel(NioServerSocketChannel.class)//設置線程隊列得到連接個數    .option(ChannelOption.SO_BACKLOG, 128)//設置保持活動連接狀態    .childOption(ChannelOption.SO_KEEPALIVE, true)//使用匿名內部類的形式初始化通道對象    .childHandler(new ChannelInitializer<SocketChannel>() {@Overrideprotected void initChannel(SocketChannel socketChannel) throws Exception {//給pipeline管道設置處理器socketChannel.pipeline().addLast(new MyServerHandler());}});//給workerGroup的EventLoop對應的管道設置處理器System.out.println("java技術愛好者的服務端已經準備就緒...");//綁定端口號,啟動服務端ChannelFuture channelFuture = bootstrap.bind(6666).sync();//對關閉通道進行監聽channelFuture.channel().closeFuture().sync();} finally {bossGroup.shutdownGracefully();workerGroup.shutdownGracefully();}}
}
/*** 自定義的Handler需要繼承Netty規定好的HandlerAdapter* 才能被Netty框架所關聯,有點類似SpringMVC的適配器模式**/
public class MyServerHandler extends ChannelInboundHandlerAdapter {@Overridepublic void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {//獲取客戶端發送過來的消息ByteBuf byteBuf = (ByteBuf) msg;System.out.println("收到客戶端" + ctx.channel().remoteAddress() + "發送的消息:" + byteBuf.toString(CharsetUtil.UTF_8));}@Overridepublic void channelReadComplete(ChannelHandlerContext ctx) throws Exception {//發送消息給客戶端ctx.writeAndFlush(Unpooled.copiedBuffer("服務端已收到消息,并給你發送一個問號?", CharsetUtil.UTF_8));}@Overridepublic void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {//發生異常,關閉通道ctx.close();}
}

客戶端

public class MyClient {public static void main(String[] args) throws Exception {NioEventLoopGroup eventExecutors = new NioEventLoopGroup();try {//創建bootstrap對象,配置參數Bootstrap bootstrap = new Bootstrap();//設置線程組bootstrap.group(eventExecutors)//設置客戶端的通道實現類型    .channel(NioSocketChannel.class)//使用匿名內部類初始化通道.handler(new ChannelInitializer<SocketChannel>() {@Overrideprotected void initChannel(SocketChannel ch) throws Exception {//添加客戶端通道的處理器ch.pipeline().addLast(new MyClientHandler());}});System.out.println("客戶端準備就緒,隨時可以起飛~");//連接服務端ChannelFuture channelFuture = bootstrap.connect("127.0.0.1", 6666).sync();//對通道關閉進行監聽channelFuture.channel().closeFuture().sync();} finally {//關閉線程組eventExecutors.shutdownGracefully();}}
}
public class MyClientHandler extends ChannelInboundHandlerAdapter {@Overridepublic void channelActive(ChannelHandlerContext ctx) throws Exception {//發送消息到服務端ctx.writeAndFlush(Unpooled.copiedBuffer("歪比巴卜~茉莉~Are you good~馬來西亞~", CharsetUtil.UTF_8));}@Overridepublic void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {//接收服務端發送過來的消息ByteBuf byteBuf = (ByteBuf) msg;System.out.println("收到服務端" + ctx.channel().remoteAddress() + "的消息:" + byteBuf.toString(CharsetUtil.UTF_8));}
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/167007.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/167007.shtml
英文地址,請注明出處:http://en.pswp.cn/news/167007.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Linux:大文件查找、切割、統計操作命令

1、查找文件夾某個文件中指定內容 grep -r -l "指定內容" /文件夾路徑 2、統計文件夾里文件個數 ll | grep ^- | wc -l 3、切割日志文件 split -b 200M -d -a 3 filename file_ 4、查看服務器磁盤里有哪些大文件夾 du -h --max-depth1 | sort -nr 5、查找/h…

MySQL數據庫入門到大牛_基礎_15_存儲過程與函數

前面我們介紹了數據自帶的函數&#xff0c;此處提到的函數&#xff0c;指的是用戶自定義函數。存儲函數是一定會有返回值的&#xff0c;存儲過程是可以沒有返回值的。 MySQL從5.0版本開始支持存儲過程和函數。存儲過程和函數能夠將復雜的SQL邏輯封裝在一起&#xff0c;應用程序…

中電金信:守【政】創新,探路保險數字化轉型“新范式”

11月23日&#xff0c;CIIP2023中國保險科技創新合作大會在京舉辦。大會匯集保險科技領域行業專家、學者、國內外頭部險企及保險科技公司負責人等各界人士&#xff0c;立足保險行業高質量發展和創新驅動理念&#xff0c;尋找行業數字化轉型新動能、新視角&#xff0c;為保險科技…

python中range函數的用法

range() 是Python的一個內置函數。語法格式為&#xff1a;range(start, stop, step) start是初始值&#xff0c;stop是最終值&#xff0c;step是步長。range()函數僅適用于整數&#xff0c;所有參數都必須是整數。步長值可以為正數或負數&#xff0c;不得為零。使用range函數時…

如何去掉圖片水印不傷原圖?無痕去水印教程分享!

如何去掉圖片水印不傷原圖&#xff1f;在電商廣告設計和營銷領域&#xff0c;水印已經成為一種常見的版權保護手段。不過&#xff0c;水印也給淘寶商家帶來了一些困擾。那么如何去掉圖片水印還能不傷原圖呢&#xff0c;接下來&#xff0c;將分享簡單好用的無痕去水印教程&#…

Rust UI開發(二):iced中如何為窗口添加icon圖標

注&#xff1a;此文適合于對rust有一些了解的朋友 iced是一個跨平臺的GUI庫&#xff0c;用于為rust語言程序構建UI界面。 想要了解如何構建簡單窗口的可以看本系列的第一篇&#xff1a; Rust UI開發&#xff1a;使用iced構建UI時&#xff0c;如何在界面顯示中文字符 本篇是系…

VMware 虛擬機設置靜態IP

1.橋接模式&#xff1a;無線網卡虛擬機可以橋接的&#xff0c;Vmware0是虛擬機默認進入的虛擬網絡&#xff0c;打開虛擬網絡編輯器把Vmware0橋接到具體的無線網卡上&#xff0c;再打開網卡設置選擇橋接模式即可。 2、.NAT模式下 &#xff1a;window下VMnet8: IPv4 地址 . . . …

Redis分片備庫切換操作

Redis分片備庫切換操作 場景描述&#xff1a; 分片集群&#xff1a; 1.ipa:5001-ipa:5002 2.ipb:5001-ipb:5002 需將兩個分片備庫互置完成災備 操作步驟 準備工作 主機密碼&#xff1a;1qaz!QAZ 獲取節點信息命令 /redispath/bin/redis-cli -a password -h ip -p port red…

軟考信息系統項目管理師考試真的越來越難了

浙江&#xff0c;深圳&#xff0c;青海&#xff0c;寧波&#xff0c;湖南等地都發布了2023年上半年的軟考合格人員名單。根據這份名單再對比一下上半年的各省軟考報名人數&#xff0c;可以看出來&#xff0c;軟考通過率確實有大幅下降的趨勢&#xff0c;信息系統項目管理師考試…

高級IO—select

高級IO—select 文章目錄 高級IO—selectIO的概念 五種IO模型阻塞IO非阻塞IO信號驅動IOIO多路轉接異步IO I/O多路轉接之select IO的概念 通常指數據在內部存儲器和外部存儲器或其他周邊設備之間的輸入和輸出。輸入是系統接收的信號或數據&#xff0c;輸出則是從其發送的信號或…

Jmeter接口測試——使用教程(下)

前言 上一篇我給大家講了jmeter的基本介紹跟參數化和jmeter腳本及jmeter斷言&#xff0c;今天讓我們繼續往下看&#xff0c;學習一下jmeter新的知識點。 一、Jmeter關聯 我們知道斷言是從返回結果中檢查有沒有預期的值&#xff0c;現在有一個問題&#xff0c;有一個購買商品…

【學習筆記】GameFramework的非官方實例TowerDefense-GameFramework-Demo的流程

一、從游戲開始到打開一個Menu GameStart.unity GameEntry.Builtin.cs ProcedureComponent.cs GameStart.unity->GameFramework->Builtin->Procedure ProcedureLaunch.cs ProcedureSplash.cs ProcedurePreload.cs ProcedureLoadingScene.cs DataTables/Scene.txt Pro…

transformers中的data_collator

前言 使用huggingface的Dataset加載數據集&#xff0c;然后使用過tokenizer對文本數據進行編碼&#xff0c;但是此時的特征數據還不是tensor&#xff0c;需要轉換為深度學習框架所需的tensor類型。data_collator的作用就是將features特征數據轉換為tensor類型的dataset。 本文…

小學語文老師重點工作

小學語文老師是學生在語言學習過程中的關鍵引導者&#xff0c;他們的主要職責是幫助學生建立正確的語言基礎&#xff0c;培養良好的閱讀習慣&#xff0c;并提高學生的語文素養。以下是小學語文老師的一些重點工作。 一、教授語言知識 小學語文老師首要的任務是教授學生語言知識…

《DApp開發:開啟全新數字時代篇章》

隨著區塊鏈技術的日益成熟&#xff0c;去中心化應用&#xff08;DApp&#xff09;逐漸成為數字世界的新焦點。在這個充滿無限可能的全新領域&#xff0c;DApp開發為創新者們提供了開啟數字時代新篇章的鑰匙。 一、DApp&#xff1a;區塊鏈創新成果 DApp是建立在區塊鏈技術基礎之…

C/C++ 開發SCM服務管理組件

SCM&#xff08;Service Control Manager&#xff09;服務管理器是 Windows 操作系統中的一個關鍵組件&#xff0c;負責管理系統服務的啟動、停止和配置。服務是一種在后臺運行的應用程序&#xff0c;可以在系統啟動時自動啟動&#xff0c;也可以由用戶或其他應用程序手動啟動。…

CMakeLists.txt:打印find_package變量;判斷庫文件路徑設定是否正確;install文件設置

CMake打印find_package變量&#xff1b;install文件設置 打印find_package找到的各種變量判斷庫文件是否被找到install文件設置install詳細說明 打印find_package找到的各種變量 目的&#xff1a;find_package后&#xff0c;想使用找到的include/lib文件夾。 find_package(Yo…

chromium通信系統-mojo系統(一)-ipcz系統基本概念

ipcz 是chromium的跨進程通信系統。z可能是代表zero&#xff0c;表示0拷貝通信。 chromium的文檔是非常豐富的&#xff0c;關于ipcz最重要的一篇官方文檔是IPCZ。 關于ipcz本篇文章主要的目的是通過源代碼去分析它的實現。再進入分析前我們先對官方文檔做一個總結&#xff0c;…

axios封裝和請求跨域和.gitignore文件

axios封裝 首先這部分網上找找應該一大堆&#xff0c;其中本人喜歡同.env文件一同配合使用&#xff1b; let base_url process.env.PROJECT_NAME if (process.env.NODE_ENV production){base_url process.env.PROJECT_BASEURL process.env.PROJECT_NAME// base_url http:…

Java計算兩個時間的相差年,日,小時,分,秒

主函數 public static int dateDiff(char flag, Calendar calSrc, Calendar calDes) {long millisDiff getMillis(calSrc) - getMillis(calDes);if (flag y) {return (calSrc.get(Calendar.YEAR) - calDes.get(Calendar.YEAR));}if (flag d) {return (int) (millisDiff / D…