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.mzph.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…