Netty定义
Netty是由JBOSS提供的一个java开源框架,现为 Github上的独立项目。Netty提供异步的、事件驱动的网络应用程序框架和工具,用以快速开发高性能、高可靠性的网络服务器和客户端程
应用场景
互联网(高性能rpc框架)
游戏行业
大数据
java 三种网络模型(IO模式)
-
BIO(blocking I/O):同步并阻塞,服务器实现模式为一个连接一个线程,即客户端有连接请求时服务器端就需要启动一个线程进行处理,如果这个连接不做任何事情会造成不必要的线程开销,当然可以通过线程池机制改善
简单流程:
服务端启动一个ServerSocket -> 客户端访问服务端,服务端对客户端建立一个线程与之通信 ->服务端有空闲线程则相应客户端,没有则等待或者拒绝连接 -> 服务端有响应则,其他客户端等待响应结束后再继续执行 -
NIO(non-blocking I/O):同步非阻塞,服务器实现模式为一个请求一个线程,即客户端发送的连接请求都会注册到多路复用器上,多路复用器轮询到连接有I/O请求时才启动一个线程进行处理.
-
AIO(Asynchronous I/O):异步非阻塞,服务器实现模式为一个有效请求一个线程,客户端的I/O请求都是由OS先完成了再通知服务器应用去启动线程进行处理(现在还没有广泛应用).
NIO的三大核心:
- Channel(通道)
- Buffer(缓冲区)
- Selector(选择器)
三者的关系:一个线程对应一个selector,selector下可以有多个channel(可看做是一个连接,类似于stream),每个channel上都存在一个Buffer(内存块,缓冲区,底层是一个数组),数据的读取通过buffer,buffer是双向的,channel也是双向的
Buffer特点及使用注意事项
- ByteBuffer类型统一,set get 类型须一致;
- 可设置Buffer只读;
- MappedByteBuffer使用;
- 可用多个Buffer完成读写操作(Scattering,Gathering)
Channel特点及使用注意事项
- Channel是双向的,可读写
Selector特点及使用注意事项
- Selector一个线程处理多个客户端连接;
- 检测多个注册的通道上是否有事件发生(Channel以事件方式注册到一个Selector),触发机制有事件发生则进行相应处理;
- 检测机制减少了线程切换的资源开销,性能更好;
NIO非阻塞网络流程关系说明:
- 客户端链接时通过ServerSocketChannel得到SocketChannel;
- SocketChannel注册到Selector上,一个selector可注册多个SocketChannel;
- 注册成功返回一个selectionKey,和Selector关联;
- Selector监听所有注册的SocketChannel,一旦监听到事件发生,可通过selectionKey获取到channel,进行相应的业务操作;
Netty线程模型
目前存在的线程模型:
- 传统阻塞I/O模型
- Reactor模型(反应器模式):三种主要实现:单Reactor单线程 单Reactor多线程,主从Reactor多线程
Netty的线程模型
基于主从Reactor多线程并对其进行了改进,主从中有多个Reactor
简单流程:
- BossGroup(专门负责接收客户端的链接)线程维护Selector,只关注Accecpt;
- 当接收到Accept事件,获取到对应的socketChannel,封装成NiosocketChannel并注册到WorkerGroup线程事件(事件循环),并进行维护;
- WorkerGroup(专门负责网络的读写)线程监听到selector中通道发生事件,调用想用的hander进行处理;
详细流程:
- BossGroup(专门负责接收客户端的链接) ,WorkerGroup(专门负责网络的读写))同属于NioEventLoopGroup;
- NioEventLoopGroup事件轮询组,包含多个事件轮询,每个事件都是一个NioEventLoop;
- NioEventLoop作为一个轮询线程,绑定一个selector,监听绑定的socket的网络通讯;
- NioEventLoopGroup与NioEventLoop可以是多对多的关系;NioEventLoopGroup可以多个,NioEventLoop也可以是多个;
- BossGroup轮询步奏流程:轮询accept事件;处理accept事件,与client建立连接,生成NioSocketChannel,并将注册到WorkerGroup下的某个NioEventLoopGroup下的NioEventLoop中的selector上; 处理任务队列任务(runAllTasks);
- 每个WorkerGroup下NioEventLoopGroup下的NioEventLoop轮询步奏流程:轮询read,write事件;在NioSocketChannel处理i/o事件(read,write事件);处理任务队列任务(runAllTasks);
- 每个NioEventLoopGroup下的NioEventLoop轮询处理业务时使用pipeline(管道),其中包含多个channel,可通过管道获取channel,管道中维护多个处理器(包含过滤,拦截等机制的处理器,以及自定义业务);
Netty中task(NioEventLoop中的一个变量负责任务执行)队列常用的三种使用场景:
- 用户自定义的普通任务(taskQueue)
- 用户自定义的定时任务(schduleQueue)
Reactor模式简介
Reactor模式:基于I/O复用模型,多个连接共用一个阻塞对象,应用程序只需要在一个阻塞对象等待,无需等待所有连接,当某个连接有新的数据处理时,操作系统通知应用程序,线程从阻塞状态中唤醒,进行相关业务处理,其中每个链接线程都在线程池中统一调度,线程池复用减少资源开销
Netty异步模型(ChannelFuture)
ChannelFuture接口实现Future接口
Future-Listener机制:future对象创建完成之后处于非完成状态,调用者通过callback来执行完成之后的操作
Netty核心组件
Bootstrap
bootstrap主要作用是配置整个netty程序,串联各个组件,netty中bootstrap是客户端程序的启动引导类
ServerBootstrap
netty中ServerBootstrap 是服务端程序的启动引导类
ChannelFuture
netty中ChannelFuture 是异步模型的主要体现,注册监听机制实现异步策略
Channel
netty中Channel 是网络通信组件,执行网络得异步I/O(ChannelFuture )操作
ChannelHandler
netty中ChannelHandler 是一个接口,处理I/O事件或拦截I/O事件,并负责转发到ChannelPipeline中处理下一个处理程序,其中主要运用他的子类进行相关业务开发
Pipeline和ChannelPipeline
netty中ChannelPipeline是一个Handler集合,它负责处理和拦截inbound或者outbound的事件和操作,双向链表获取前后的Handler以及处理器的Handler的上下文
ChannelHandlerContext
保存Channel的相关的所有上下文信息,同时关联一个ChannelHandler对象,同时也绑定一个对应的pipeline 和 channel信息
ChannelOption参数
- ChannelOption.SO_BACKLOG 对应TCP/IP 协议listen函数中的backlog参数,用来初始化服务器的连接队列大小
- ChannelOption.SO_KEEPALIVE 一直保持连接活动状态
EventLoopGroup 和其实现类NioEventLoopGroup
EventLoopGroup是一组EventLoop的抽象,同时会有多个EventLoop同时工作,每个EventLoop维护一个Selector
Unpooled类
操作缓冲区的工具类,类似于Nio中的ByteBuffer,在Netty中不需要flip进行读写反转,自身底层维护了readerindex和writerindex 以及capacity 来进行读写反转