通过以上对Channel和ChannelPipeline的源码解读,想必大家已知晓Channel、ChannelPipeline和 ChannelHandler 三者的关系,正如图所示:
Netty 正是通过 ChannelPipeline 这一结构为用户提供了自定义业务逻辑的扩展点,用户只需要向 ChannelPipeline 中添加处理对应业务逻辑的 ChannelHandler,之后当指定事件发生时,该 ChannelHandler 中的对应方法就会进行回调,实现业务的处理。
打个比喻,每个 channel 是一个产品的加工车间,pipeline 是车间中的流水线,channelHandler 就是流水线上的各道工序,byteBuf 是原材料,经过很多工序的加工:先经过一道道入站工序,再经过一道道出站工序最终变成产品。
ChannelHandler 基于责任链模式实现,负责对IO事件进行拦截和处理, 也可以终止事件的传递。ChannelHandler 有两个重要的子接口:ChannelInboundHandler和ChannelOutboundHandler,分别拦截入站和出站的各种 I/O 事件。
ChannelHandler支持注解,Netty提供了2个:
Sharable
:多个ChannelPipline公用同一个ChannelHandlerSkip
:被Skip注解的方法不会被调用ChannelDuplexHandler是双工处理器,具有ChannelInboundHandler和ChannelOutboundHandler的功能
ChannelInboundHandler 处理入站数据以及各种状态变化,当 channel 状态发生改变会调用 ChannelInboundHandler 中的一些生命周期方法,以下罗列ChannelInboundHandler的事件回调方法与触发时机!
pipeline.fireChannelRegistered()
。pipeline.fireChannelUnregistered()
pipeline.fireChannelActive()
pipeline.fireChannelInactive()
pipeline.fireChannelRead()
pipeline.fireChannelReadComplete()
pipeline.fireChannelWritabilityChanged()
ctx.fireUserEventTriggered(evt)
我们可以看出,Inbound事件都是由I/O线程触发,用户实现部分关注的事件被动调用
ChannelInboundHandlerAdapter
作为ChannelInboundHandler
的实现,默认将入站事件自动传播到下一个入站处理器。其中的代码高度一致,如channelRead()
:
查找通道中的下一个Inbound
private AbstractChannelHandlerContext findContextInbound(int mask) {
AbstractChannelHandlerContext ctx = this;
do {
ctx = ctx.next;
} while ((ctx.executionMask & mask) == 0);
return ctx;
}
ChannelOutboundHandler 的事件回调方法与触发时机!此外 ChannelOutboundHandler 中绝大部分接口都包含ChannelPromise 参数,以便于在操作完成时能够及时获得通知。
同理,ChannelOutboundHandlerAdapter
作为ChannelOutboundHandler
的事件,默认将出站事件传播到下一个出站处理器~