目录
3、链表中的事件结点:ChannelHandlerContext
4、创建初始化通道对象:ChannelInitializer类
8、端启动助手及设置线程组:ServerBootstrap和Bootstrap
NIO学习完,发现一个问题就是---NIO的类库和API也太繁杂了!使用起来就很麻烦,几个小demo给我搞得眼花缭乱....
这时Netty出现了。
一、Netty是什么
Netty是一个基于NIO的网络编程框架。它提供异步的、基于事件驱动的网络应用程序框
架,用以快速开发高性能、高可靠性的网络 IO 程序。
二、Reactor模型
1、单Reactor单线程
图为单线程的Reator模型(我理解的)。
2、单Reactor多线程
多线程情况下也不难,只是多了几个Hardler,而Harlder只负责响应事件(read和send)而不做具体的业务处理,它会麻烦worker线程池,找一个worker线程去处理业务,read后分发任务给线程处理,处理完返回给Hardler,然后send给client。
会突然发现这个Reactor模型好眼熟,不觉得很像NIO吗?其实两者机制很像,可以理解为Reactor模型是基于NIO产生的(可以勉强这么理解,实际上这两个东西的性质不统一)
3、主从Reactor多线程
这回就更复杂了,Reactor线程变成了两个。但其实机制和上面的多线程状态也差不多:此时Reactor主线程只负责监听客户端连接请求,和客户端建立连接之后就将连接交由Reactor子线程监听后面的 IO 事件。
- Reactor主线程对象监听客户端连接事件
- 收到事件后,通过Acceptor处理客户端连接事件
- 当Acceptor连接好后,Reactor主线程将连接分配给Reactor子线程
- 子线程将连接加入自己的连接队列监听,并创建Handler对各种事件进行处理
- 当连接上有新事情发生时,子线程调用对应的Handler处理
- Handler通过read从连接上读取请求数据,将请求发给 Worker 线程池进行业务处理
- 可怜的worker线程终于处理好业务了,返回给Handler,然后Handler用send返回给客户端
一个 Reactor主线程 可以对应多个 Reactor子线程
其实说白了就是一个接着一个丢锅都不愿意干活,最后层层传递交给最底层的worker线程干。
三、Netty线程模型
又回归到我们的Netty。前面为什么介绍了Reactor模型呢?因为Netty基于主从 Reactor 多线程模式。
1、从简理解:Boss和Worker线程
- BossGroup 线程(类似于主 Reactor)中维护 Selector,ServerSocketChannel 注册到Selector上,只关注建立连接请求事件;
- 当接收到来自客户端的连接时,通过 ServerSocketChannel.accept ()获得对应的 SocketChannel,并封装成 NioSocketChannel 注册到 WorkerGroup 线程(类似于从 Reactor)中的Selector(每个 Selector 运行在一个线程中);
- 当 WorkerGroup 线程中的 Selector 监听到自己感兴趣的事就调用 Handler 处理
2、进阶详细学习:Boss和Worker线程池
抽象出了两组线程池:BossGroup线程池中的线程负责和客户端建立连接,WorkerGroup线程池中的的线程负责处理连接上的读写。
两个线程池的类型都是NioEventLoopGroup(事件循环组)。事件循环线程池中的每个线程都配有一个selector用于监听管道Channa上l是否有连接。
BossGroup循环执行以下三个步骤:
- select:轮询连接事件(OP_ACCEPT事件)
- processSelectedKeys事件:处理连接事件,与客户端连接生成NioSocketChannal,并将其注册到WorkerGroup的selector上
- runAllTasks:再以此循环处理事件队列中的其他事件
WorkerGroup循环执行以下三个步骤:
- select:轮询注册了的NioSocketChannal的读写事件(OP_READ和OP_WRITE事件)
- processSelectorKeys事件:处理读写事件
- runAllTasks:再以此循环处理事件队列中的其他事件
四、Netty核心API
1、事件处理器:ChannelHandler接口及其实现类
ChannelHandler接口下定义了很多事件处理的方法。当我们使用Netty进行网络编程时,需要自定义一个Handler类实现ChannelHandler接口或其实现类,然后重写对应方法实现业务逻辑。
- public void channelActive(ChannelHandlerContext ctx),通道就绪事件
- public void channelRead(ChannelHandlerContext ctx, Object msg),通道读取数据事件
- public void channelReadComplete(ChannelHandlerContext ctx) ,数据读取完毕事件
- public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause),通道发生异常事件
2、事件处理链表:ChannelPipeline接口
ChannelPipeline类是ChannelHandler实例对象的链表,用于处理或截获通道的接收和发送数据。对于每个新的通道Channel,都会创建一个新的C