概述
之前学习的Reactor模型只是懂得了服务器端如何把一个连接放到workergroup中处理,那么真正处理某一个具体的请求的过程是什么样的呢
基本概念
我们知道数据的读取都是通过channel来完成的,Netty在channel的IO事件中定义了许多的生命周期函数,Netty将这些生命周期函数封装在Handler中,通过责任链的模式封装在了一个 pipeline中。当 channel中触发了对应的IO事件,就会调用pipeline中的头或者尾的一个handler,至于是否传递到下一级,由对应的handler判断.
Netty把IO事件分成两类,一个是Netty从网络中读取数据,成为InBound。一个是Netty把数据写到网络中,成为OutBound。Handler也被分成ChannelInBoundHandler和ChannelOutBoundHandler,他们各自有着不同的生命周期函数
pipeline是要给双向链表,有着头尾两个指针,inbound事件是从head节点往后传播,outbound事件是从tail节点往前传播
为了能让handler更加的灵活,Netty给handler外面包了一层的 HandlerContext. context允许handler在生命周期方法中直接改变数据的流向,比如读完数据就可以让 context在把数据写出去,那么数据的流向就从 inbound变成了outbound
InboundHandler
public interface ChannelInboundHandler extends ChannelHandler {
# channel 注册到eventLoop
void channelRegistered(ChannelHandlerContext ctx) throws Exception;
# channel从eventloop中取消注册
void channelUnregistered(ChannelHandlerContext ctx) throws Exception;
# channel已经建立了连接
void channelActive(ChannelHandlerContext ctx) throws Exception;
# channel结束了连接
void channelInactive(ChannelHandlerContext ctx) throws Exception;
# channel从网络中读到了数据
void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception;
# channel读取完数据
void channelReadComplete(ChannelHandlerContext ctx) throws Exception;
# 读取数据中发生了异常调用该方法
void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception;
}
复制代码
我们来看看-生命周期的调用源码。
channelRegistered: 在AbstractChannel方法中register方法中
private void register0(ChannelPromise promise) {
try {
# 这里就是让 channel注册到eventloop并且注册到selector中的方法
doRegister();
# 注册结束之后就会调用 pipeline的fireChannelRegistered方法
pipeline.fireChannelRegistered();
if (isActive()) {
if (firstRegistration) {
# 如果是激活状态还会调用 fireChannelActive 方法
pipeline.fireChannelActive();
} else if (config(</