一、Netty介绍
Netty是一个高性能、异步事件驱动的NIO框架,提供了对TCP、UDP和文件传输的支持,作为一个异步NIO框架,Netty的所有IO操作都是异步非阻塞的,通过Future-Listener机制,用户可以方便的主动获取或者通过通知机制获得IO操作结果。
Netty的核心核心组件:
- Channel
- 回调
- Future
- 事件和ChannelHandler
这些构建代表了不同类型的构造:资源、逻辑以及通知。你的应用程序将使用它们来访问网络以及流经网络的数据
(1)Channel
Channel是Java NIO的一个基本构造,代表一个到实体的开放连接,如读操作和写操作,可以把Channel看作传入(入站)或者出传(出战)数据的载体。因此它可以被打开或被关闭,连接或者断开连接
(2)回调
Netty在内部使用了回调来处理事件,当一个回调被触发时,相关的事件可以被一个ChannelHandler的实现处理。
(3)Future
Future提供了另一种在操作完成时通知应用程序的方式,这个对象可以看作一个异步操作的结果的占位符(占位符就是先占住一个固定的位置,等着你再往里面添加内容的符号),它在未来的某个时刻完成,并提供对其结果的访问
ChannelFuture提供了几种额外的方法,这些方法使得我们能够注册一个或多个ChannelFutureListener实例,监听器的回调方法operationComplete(),将会在对应的操作完成时被调用,然后在监听器可以判断该操作是成功完成还是出错了,如果是后者,我们可以检索产生的Throwable
每个Netty的出战I/O操作都将返回一个ChannelFuture;他们都不会阻塞,Netty完全是异步和事件驱动的
(4)事件和ChannelHandler
Netty使用不同的事件来通知我们状态的改变或者操作的状态,这使我们能够基于已经发生的事件来触发适当的动作,这些作用可能是:
- 记录日志
- 数据转换
- 流控制
- 应用程序逻辑
Netty所有事件是按照它们与性入站或出战数据流的相关性分类,可能由入站数据或者相关的状态更改而触发的事件包括:
- 连接已被激活或者连接失活
- 数据读取
- 用户事件
- 错误事件
出站事件是未来将会触发的某个动作的操作结果,这些动作包括
- 打开或者关闭到远程节点的连接
- 将数据到或者冲刷到套接字
二、Netty服务端创建时序图
步骤一、创建ServerBootstrap实例,ServerBootstrap是Netty服务端启动辅助类,它提供了一系列的方法用于设置服务端启动相关的参数,底层通过门面模式对各种能力和接口进行封装
步骤二、设置和绑定Reactor线程池:Netty的Reactor线程池是EventLoopGroup,它实际上就是EventLoop数组,EventLoop负责处理所有注册到本线程多路复用器Selector上的channel,Selector的轮询操作由绑定的EventLoop线程run方法驱动,在一个循环体内循环执行,他不仅处理网络的I/O事件,用户自定义的Task和定时任务Task也统一由EventLoop负责处理,这样线程模型实现了统一,这样即避免了多线程并发操作和锁竞争,提升了I/O线程的处理和调度性能
步骤三、设置并绑定服务端Channel,作为NIO服务器,需要创建ServerSocketChannel,我们只需使用Netty的ServerBootstrap方法提供了channel方法用于指定服务端Channel的类型即可,Netty会通过工厂类,通过反射创建NioServerSocketChannel对象,因为服务端监听端口只需要在系统启动时才调用,所以对性能影响不大
步骤四、链路建立的时候创建并初始化ChannelPipeline,ChannelPipeline并不是NIO服务端必需,本质是一个负责网络事件的职责链,负责和执行ChannelHandler,网络事件以事件流的形式在Channel流转,由ChannelPipeline根据ChannelHandler的执行策略调度ChannelHandler的执行
步骤五、添加并设置ChannelHandler,利用ChannelHandler实现大多数功能的定制
步骤六、绑定并启动监听端口,在绑定监听端口之前系统会做一系列初始化和检测工作,完成之后,会启动监听端口,并将ServerSocketChannel注册到Selector上监听客户端连接
步骤七、Selector轮询,由NIoEventLoop负责调度和执行Selector轮询操作,选择准备就绪的Channel集合
步骤八、当轮询到准备就绪的Channel之后,就由Reactor线程NioEventLoop执行ChannelPipeline的相应方法,最终调度并执行ChannelHandler
三、Netty工作原理架构图
server端工作原理:
server端启动时绑定本地某个端口,将自己NioServerSocketChannel注册到某个boss NioEventLoop的selector上。
server端包含1个boss NioEventLoopGroup和1个worker NioEventLoopGroup,NioEventLoopGroup相当于1个事件循环组,这个组里包含多个事件循环NioEventLoop,每个NioEventLoop包含1个selector和1个事件循环线程。
每个boss NioEventLoop循环执行的任务包含3步:
- 第1步:轮询accept事件;
- 第2步:处理io任务,即accept事件,与client建立连接,生成NioSocketChannel,并将NioSocketChannel注册到某个worker NioEventLoop的selector上;
- 第3步:处理任务队列中的任务,runAllTasks。任务队列中的任务包括用户调用eventloop.execute或schedule执行的任务,或者其它线程提交到该eventloop的任务。
每个worker NioEventLoop循环执行的任务包含3步:
- 第1步:轮询read、write事件;
- 第2步:处理io任务,即read、write事件,在NioSocketChannel可读、可写事件发生时进行处理;
- 第3步:处理任务队列中的任务,runAllTasks。
client端工作原理:
client端启动时connect到server,建立NioSocketChannel,并注册到某个NioEventLoop的selector上。
client端只包含1个NioEventLoopGroup,每个NioEventLoop循环执行的任务包含3步:
- 第1步:轮询connect、read、write事件;
- 第2步:处理io任务,即connect、read、write事件,在NioSocketChannel连接建立、可读、可写事件发生时进行处理;
- 第3步:处理非io任务,runAllTasks。