ChannelPipeline是Channelhandler的容器,它负责ChannelHandler的管理和事件拦截与调度。
土话:
ChannelPipeline就是用来管理Channelhandler有增删功能。还有一些事件的拦截,交给ChannelHandler处理。
关于阅读源码的步骤,请参考这份源码阅读步骤你值得拥有
ChannelPipeline的功能
管理ChannelHandler
- addXXX:增加ChannelHandler
- get:获得ChannelHandler
- remove:移除ChannelHandler
- replace:代替ChannelHander
拦截ChannelHandler的事件,这里比较重要
从图中看
- 从Socket.read()经过ChannelHandler1,ChannelHandler2....ChannelHandlerN开始称为inbound事件。
- 从ChannelHandlerContext开始经过ChannelHandlerN,ChannelHandlerN-1,...一直到ChannelHandler1,Socket.write()称为outbound事件。
inbound事件对应ChannelInboundInvoker类
inbound事件通常由I/O线程触发,例如TCP链路建立事件,链路关闭事件,读事件,异常通知事件等。
public interface ChannelInboundInvoker { //Channel注册事件 //Channel注册成功后会执行该方法,对应的地方AbstractChannel.register0方法 ChannelInboundInvoker fireChannelRegistered(); //取消注册事件 //取消注册后调用,对应的地方AbstractChannel.deregister ChannelInboundInvoker fireChannelUnregistered(); //TCP链路建立成功,Channel激活事件,客户端与服务端建立连接 //客户端发起请求后 //服务端会从ServerBootstrapAcceptor会收到channelRead,childGroup注册一个child //对应的地方是AbstractChannel.register0 //客户端则再连接成功后对应的地方AbstractNioChannel.fulfillConnectPromise ChannelInboundInvoker fireChannelActive(); //客户端与服务端断开连接的时候调用 ChannelInboundInvoker fireChannelInactive(); //异常的通知事件 ChannelInboundInvoker fireExceptionCaught(Throwable cause); //用户自定义事件 //就是我们定义ChannelHandler的时候可以调用我们自定义的fireUserEventTriggered ChannelInboundInvoker fireUserEventTriggered(Object event); //读数据事件 //对应调用的地方是NioUnsafe.read ChannelInboundInvoker fireChannelRead(Object msg); //读操作完成 //对应调用的地方是NioUnsafe.read读完后调用 ChannelInboundInvoker fireChannelReadComplete(); //channel的可写状态变化通知事件 ChannelInboundInvoker fireChannelWritabilityChanged();}
上面的每个方法都很重要,我们要自定义ChannelHandler的时候必须要知道怎么调用这些方法。
outbound事件对应ChannelOutboundInvoker类
outbound通常是由用户主动发起的网络I/O操作,例如用户发起的连接操作,绑定操作,消息发送等操作。
public interface ChannelOutboundInvoker { //bind本地地址事件 ChannelFuture bind(SocketAddress localAddress); //连接服务端事件 ChannelFuture connect(SocketAddress remoteAddress); ChannelFuture connect(SocketAddress remoteAddress, SocketAddress localAddress); //断开连接事件 ChannelFuture disconnect(); //关闭当前channel事件 ChannelFuture close(); //取消注册事件 ChannelFuture deregister(); ChannelFuture bind(SocketAddress localAddress, ChannelPromise promise); ChannelFuture connect(SocketAddress remoteAddress, ChannelPromise promise); ChannelFuture connect(SocketAddress remoteAddress, SocketAddress localAddress, ChannelPromise promise); ChannelFuture disconnect(ChannelPromise promise); ChannelFuture close(ChannelPromise promise); ChannelFuture deregister(ChannelPromise promise); //读事件 ChannelOutboundInvoker read(); //发送事件 ChannelFuture write(Object msg); ChannelFuture write(Object msg, ChannelPromise promise); //刷新事件 ChannelOutboundInvoker flush(); //写和刷新事件 ChannelFuture writeAndFlush(Object msg, ChannelPromise promise); ChannelFuture writeAndFlush(Object msg); ChannelPromise newPromise(); ChannelProgressivePromise newProgressivePromise(); ChannelFuture newSucceededFuture(); ChannelFuture newFailedFuture(Throwable cause); ChannelPromise voidPromise();}
我们扩展事件一般是在inbound事件。
核心类DefaultChannelPipeline
DefaultChannelPipeline是Netty用来管理ChannelHandler的核心类
DefaultChannelPipeline
protected DefaultChannelPipeline(Channel channel) { this.channel = ObjectUtil.checkNotNull(channel, "channel"); succeededFuture = new SucceededChannelFuture(channel, null); voidPromise = new VoidChannelPromise(channel, true); tail = new TailContext(this); head = new HeadContext(this); head.next = tail; tail.prev = head;}
分析DefaultChannelPipeline关键成员变量
- head:是现实HeadContext继承了AbstractChannelHandlerContext,AbstractChannelHandlerContext就是Channelhandler的上下文。DefaultChannelPipeline包含了很多ChannelHander,指向第一个事件
- tail:对应TailContext,指向DefaultChannelPipeline的末尾事件。
- channel:注册的channel,例如服务端对应的就是NioSockerServerChannel,客户端对应的就是NioSocketChannel。
- pendingHandlerCallbackHead:当执行完了handler的增加删除操作后调用,用来做回调处理。
- registered:AbstractChannel是否注册,一旦注册了就不会再改变了
分析AbstractChannelHandlerContext类
- AttributeMap,DefaultAttributeMap一些参数的定义Map
- ResourceLeakHint:就是用来定义做一些提示,打印一些自定义参数用的。
- ChannelHandlerContext:它代表了 ChannelHandler 和ChannelPipeline 之间的关联。接口ChannelHandlerContext 主要是对通过同一个 ChannelPipeline 关联的 ChannelHandler 之间的交互进行管理。
ChannelHandlerContext就是结合了ChannelInboundInvoker和ChannelOutboundInvoker,然后多了一些Handler的处理,比如说名称,获得ChannelHandler等等。
阅读源码知识点:
刚开始设计框架的时候,开发者也不会说设计的很完善,都是后面设计之后,慢慢抽象出来的。例如你要问我为什么要设计一个ChannelHandlerContext出来,我只能跟你说,有一些抽象方法ChannelInboundInvoker和ChannelOutboundInvoker没有必须要有一个新的接口聚合它两,并且要提供一些方法。
再来看AbstractChannelHandlerContext成员变量
- AbstractChannelHandlerContext next:头结点
- AbstractChannelHandlerContext prev:尾结点
- inBound:是否为inbound事件
- outbound:是否为outbound事件
AbstractChannelHandlerContext的结构是一个双链表
AbstractChannelHandlerContext结构
再来分析DefaultChannelHandlerContext类
final class DefaultChannelHandlerContext extends AbstractChannelHandlerContext { private final ChannelHandler handler; DefaultChannelHandlerContext( DefaultChannelPipeline pipeline, EventExecutor executor, String name, ChannelHandler handler) { super(pipeline, executor, name, isInbound(handler), isOutbound(handler)); if (handler == null) { throw new NullPointerException("handler"); } this.handler = handler; }
主要就是封装handler成一个Context
分析HeadContext类
final class HeadContext extends AbstractChannelHandlerContext implements ChannelOutboundHandler, ChannelInboundHandler
HeadContext实现了ChannelOutboundHandler,ChannelInboundHandler。上面说过outbound事件是一些网络I/O操作,例如用户发起的连接操作,绑定操作,消息发送等操作。intbound:CP链路建立事件,链路关闭事件,读事件,异常通知事件等。
分析TailContext类
final class TailContext extends AbstractChannelHandlerContext implements ChannelInboundHandler
TailContext只实现了ChannelInboundHandler,但是它的一些inbound事件都不能使用,因为HeadContext已经使用了。
@Override public void channelActive(ChannelHandlerContext ctx) throws Exception { onUnhandledInboundChannelActive(); } @Override public void channelInactive(ChannelHandlerContext ctx) throws Exception { onUnhandledInboundChannelInactive(); } @Override public void channelWritabilityChanged(ChannelHandlerContext ctx) throws Exception { onUnhandledChannelWritabilityChanged(); }
onUnhandledXXXX:就表示do noting。
小结一下,本篇讲解了
- ChannelPipeline的功能,是用来管理Channelhandler,和拦截事件请求。
- 分析了ChannelPipeline的inbound事件通常由I/O线程触发,例如TCP链路建立事件,链路关闭事件,读事件,异常通知事件等。outbound通常是由用户主动发起的网络I/O操作,例如用户发起的连接操作,绑定操作,消息发送等操作。
- 核心类DefaultChannelPipeline的功能
- 核心类DefaultChannelPipeline的成员变量AbstractChannelHandlerContext是一个双向链表,它用来保存Channelhandler
- 核心类DefaultChannelPipeline的成员变量,HeadContext指向AbstractChannelHandlerContext的头部,TailContext指向AbstractChannelHandlerContext尾部。
下篇讲解ChannelPipeline源码解析二,主要分析DefaultChannelPipeline中的核心方法。