Netty架构
文章目录
- Netty架构
- 前置知识:Reactor模型
- 单Reactor+单线程模型
- 单Reactor+多线程模型
- 主从Reactor+多线程模型
- Netty的Reactor模型
- Netty的简介
- 优势
- 服务端处理流程
- Netty的核心组件
- ChannelFuture以及ChannelFutureListener
- Channel
- ChannelPipeline
- ChannelHandler
- ChannelHandlerContext
- Bootstrap、ServerBootstrap
- Selector
- NioEventLoop
- NioEventLoopGroup
- 参考
前置知识:Reactor模型
Doug Lea在 “Scalable IO in Java” 中给了很好的阐述。NIO中Reactor的核心是Selector。Reactor 模式的典型实现:
单Reactor+单线程模型
这种单线程模型不能充分利用多核资源,所以实际使用的不多。
单Reactor+多线程模型
Tomcat使用的这种模型
主从Reactor+多线程模型
Netty的Reactor模型
Netty的简介
优势
- 使用NioEventLoop(聚合一个Selector)线程组负载均衡的处理请求。一个NioEventLoop聚合了一个多路复用器Selector,因此可以处理成百上千的客户端连接,Netty的处理策略是每当有一个新的客户端接入,则从NioEventLoop线程组中顺序获取一个可用的NioEventLoop,当到达数组上限之后,重新返回到0,通过这种方式,可以基本保证各个NioEventLoop的负载均衡。一个客户端连接只注册到一个NioEventLoop上,这样就避免了多个IO线程去并发操作它。
- Netty通过串行化设计理念降低了用户的开发难度,提升了处理性能。利用线程组实现了多个串行化线程水平并行执行,线程之间并没有交集,这样既可以充分利用多核提升并行处理能力,同时避免了线程上下文的切换和并发保护带来的额外性能损耗。
服务端处理流程
server端通常设置为包含1个Boss NioEventLoopGroup和1个Worker NioEventLoopGroup,NioEventLoopGroup相当于1个事件循环组,这个组里可以包含多个事件循环NioEventLoop,通常设置Boss NioEventLoopGroup为1个NioEventLoop,work NioEventLoopGroup为N个NioEventLoop。
每个Boss NioEventLoop循环执行的任务包含3步:
- 轮询accept事件
- 处理accept I/O事件,与Client建立连接,生成NioSocketChannel,并将NioSocketChannel注册到某个Worker NioEventLoop的Selector上
- 处理任务队列中的任务,runAllTasks。任务队列中的任务包括用户调用eventloop.execute或schedule执行的任务,或者其它线程提交到该eventloop的任务。
每个Worker NioEventLoop循环执行的任务包含3步:
- 轮询read、write事件;
- 处I/O事件,即read、write事件,在NioSocketChannel可读、可写事件发生时进行处理
- 处理任务队列中的任务,runAllTasks。
Netty的核心组件
ChannelFuture以及ChannelFutureListener
Netty 框架中所有的 I/O 操作都为异步的,因此我们需要 ChannelFuture 的 addListener()注册一个 ChannelFutureListener 监听事件,当操作执行成功或者失败时,监听就会自动触发返回结果。
Channel
- 提供异步的网络I/O操作(如建立连接,读写,绑定端口),异步调用意味着任何I / O调用都将立即返回,并且不保证在调用结束时所请求的I / O操作已完成。调用立即返回一个ChannelFuture实例,通过注册监听器到ChannelFuture上,可以I / O操作成功、失败或取消时回调通知调用方。
不同协议、不同的阻塞类型的连接都有不同的 Channel 类型与之对应,下面是一些常用的 Channel 类型
- NioSocketChannel,异步的客户端 TCP Socket 连接
- NioServerSocketChannel,异步的服务器端 TCP Socket 连接
- NioDatagramChannel,异步的 UDP 连接
- NioSctpChannel,异步的客户端 Sctp 连接
- NioSctpServerChannel,异步的 Sctp 服务器端连接 这些通道涵盖了 UDP 和 TCP网络 IO以及文件 IO.
ChannelPipeline
-
为 ChannelHandler 链提供了容器,当 channel 创建时,就会被自动分配到它专属的 ChannelPipeline,这个关联是永久性的。
-
在 Netty 中每个 Channel 都有且仅有一个 ChannelPipeline 与之对应, 它们的组成关系如下:
一个 Channel 包含了一个 ChannelPipeline, 而 ChannelPipeline 中又维护了一个由 ChannelHandlerContext 组成的双向链表, 并且每个 ChannelHandlerContext 中又关联着一个 ChannelHandler。入站事件和出站事件在一个双向链表中,入站事件会从链表head往后传递到最后一个入站的handler,出站事件会从链表tail往前传递到最前一个出站的handler,两种类型的handler互不干扰。
ChannelHandler
每一个ChannelHandlerContext组合了一个ChannelHandler实例成员。充当了所有处理入站和出站数据的逻辑容器。ChannelHandler 主要用来处理各种事件,这里的事件很广泛,比如可以是连接、数据接收、异常、数据转换等。
方便使用期间,可以继承它的子类:
-
ChannelInboundHandler 用于处理入站 I/O 事件。
-
ChannelOutboundHandler 用于处理出站 I/O 操作。
或者使用以下适配器类:
-
ChannelInboundHandlerAdapter 用于处理入站 I/O 事件。
-
ChannelOutboundHandlerAdapter 用于处理出站 I/O 操作。
-
ChannelDuplexHandler 用于处理入站和出站事件。
ChannelHandlerContext
保存Channel相关的所有上下文信息,同时关联一个ChannelHandler对象,常见的ChannelHandlerContext如下:
提供了一些方法保证ChannelHandler链式调用
- DefaultChannelHandlerContext初始化了handler,让Handler处理真正的逻辑
- AbstractChannelHandlerContext对应的pipeline、executor、prev和next
- AbstractChannelHandlerContext 提供了使得链路运转的方法
- findContextOutbound/Inbound
- inbound找下一个MASK_ONLY_INOUND的next
- ounbound 找下一个MASK_ONLY_OUTBOUND的 prev
- 一系列的invoke和fire方法
- fireChannelActive,通过findContextInbound找到下一个context,再通过invoke进行具体的调用
- invokeChannelActive(ctx)是上一个ctx调用下一个ctx,ctx调用本身的方法是不带参数的invokeChannelActive
Bootstrap、ServerBootstrap
Bootstrap意思是引导,一个Netty应用通常由一个Bootstrap开始,主要作用是配置整个Netty程序,串联各个组件,Netty中Bootstrap类是客户端程序的启动引导类,ServerBootstrap是服务端启动引导类。
Selector
Netty基于Selector对象实现I/O多路复用,通过 Selector, 一个线程可以监听多个连接的Channel事件, 当向一个Selector中注册Channel 后,Selector 内部的机制就可以自动不断地查询(select) 这些注册的Channel是否有已就绪的I/O事件(例如可读, 可写, 网络连接完成等),这样程序就可以很简单地使用一个线程高效地管理多个 Channel 。
NioEventLoop
NioEventLoop中维护了一个线程和任务队列,支持异步提交执行任务,线程启动时会调用NioEventLoop的run方法,执行I/O任务和非I/O任务:
- I/O任务 即selectionKey中ready的事件,如accept、connect、read、write等,由processSelectedKeys方法触发。
- 非IO任务 添加到taskQueue中的任务,如register0、bind0等任务,由runAllTasks方法触发。
两种任务的执行时间比由变量ioRatio控制,默认为50,则表示允许非IO任务执行的时间与IO任务的执行时间相等。
NioEventLoopGroup
NioEventLoopGroup,主要管理eventLoop的生命周期,可以理解为一个线程池,内部维护了一组线程,每个线程(NioEventLoop)负责处理多个Channel上的事件,而一个Channel只对应于一个线程。
参考
- https://www.jianshu.com/p/87f438abbd5d
- https://juejin.cn/post/7049490068888616991
- https://mp.weixin.qq.com/s?__biz=MzU3MzgwNTU2Mg==&mid=2247487309&idx=2&sn=a33cc56116cb7891145394f9c5353be3&chksm=fd3d49d8ca4ac0ce28cd0a543109d60db47e8be60d63c6951fa30e4ab4c812f9025286fa5c37&scene=21#wechat_redirect
- findContextOutbound/Inbound
-
-
猜你喜欢
网友评论
- 搜索
- 最新文章
- 热门文章