所谓Netty5的事件分发模型,主要指的是ChannelPipline, ChannelHandlerContext, ChannelHandlerInvoker, ChannelHandler, Unsafe 这几个核心接口之间的交互模型。
首先是ChannelPipline接口,它是Netty中事件分发的路径。每个Channel都会绑定一个ChannelPipeline来分发事件。
public interface Channel extends AttributeMap, Comparable<Channel> { ChannelPipeline pipeline(); }
1. 链表的接口,包括各种遍历,修改链表的操作
2. inbound事件的接口,以fireXXXX开头的方法
3. outbound事件的接口, 不带fire的方法,比如read, write,bind, connect等
inbound,outbound事件是Netty抽象的事件概念,从底层IO事件到用户事件的方向是inbound事件,从用户事件到底层IO事件的方向是outbound事件
DefaultChannelPipeline是ChannelPipeline接口的具体实现,它处理实际的事件分发。它采用了两个单链表head, tail 来处理inbound,outbound事件。
单链表的节点是ChannelHandlerContext,它通过next, prev两个指针指向前后的节点。
head链表的第一个节点是HeadHandler, tail节点的第一个节点是TailHandler。 HeadHandler里面封装了Unsafe接口, 来进行实际的IO读写。inbound事件从底层IO开始,outbound事件到底层IO结束,所以inbound事件链的起点从HeadHandler开始,outbound事件链的终点在HeadHandler结束
在上一篇将Netty如何注册OP_ACCEPT,OP_READ事件时 http://blog.csdn.net/iter_zc/article/details/39396169,我们看到每次Channel注册到Selector时,只设置了Attachment,没有真正的注册,真正的注册是在注册后调用Channel.read,通过HeadHandler的read方法,调用到AbstractChannel的doBeginRead来把OP_ACCEPT,OP_READ设置到SelectionKey的interestOps中
final class DefaultChannelPipeline implements ChannelPipeline { final DefaultChannelHandlerContext head; final DefaultChannelHandlerContext tail; public DefaultChannelPipeline(AbstractChannel channel) { if (channel == null) { throw new NullPointerException("channel"); } this.channel = channel; TailHandler tailHandler = new TailHandler(); tail = new DefaultChannelHandlerContext(this, null, generateName(tailHandler), tailHandler); HeadHandler headHandler = new HeadHandler(channel.unsafe()); head = new DefaultChannelHandlerContext(this, null, generateName(headHandler), headHandler); head.next = tail; tail.prev = head; } } final class DefaultChannelHandlerContext extends DefaultAttributeMap implements ChannelHandlerContext { volatile DefaultChannelHandlerContext next; volatile DefaultChannelHandlerContext prev; private final AbstractChannel channel; private final DefaultChannelPipeline pipeline; private final String name; private final ChannelHandler handler; private boolean removed; final int skipFlags; // Will be set to null if no child executor should be used, otherwise it will be set to the // child executor. final ChannelHandlerInvoker invoker; private ChannelFuture succeededFuture; } static final class HeadHandler extends ChannelHandlerAdapter { protected final Unsafe unsafe; protected HeadHandler(Unsafe unsafe) { this.unsafe = unsafe; } }
ChannelHandlerContext,它相当于链表中的节点,从上面的代码中可以看到,它关联了一个ChannelHandler和ChannelHandlerInvoker。
ChannelHandlerInvoker封装了线程池调用ChannelHandler的接口。DefaultChannelHandlerInvoker是默认实现,它关联了一个EventExecutor来实际执行ChannelHandler,这里实际的对象是NioEventLoop,使用单线程来执行一个Channel所有的ChannelHandler。
DefaultChannelHandlerInvoker使用了ChannelHandlerInvokerUtil来调用ChannelHandler的方法。这里我们看到ChannelHandlerInvoker的模型
1. DefaultChannelHandlerInvoker负责选择执行的线程
2. ChannelHandlerInvokerUtil调用ChannelHandler的方法
public class DefaultChannelHandlerInvoker implements ChannelHandlerInvoker { private final EventExecutor executor; @Override public void invokeChannelRegistered(final ChannelHandlerContext ctx) { if (executor.inEventLoop()) { invokeChannelRegisteredNow(ctx); } else { executor.execute(new Runnable() { @Override public void run() { invokeChannelRegisteredNow(ctx); } }); } } public abstract class SingleThreadEventLoop extends SingleThreadEventExecutor implements EventLoop { private final ChannelHandlerInvoker invoker = new DefaultChannelHandlerInvoker(this); } public final class ChannelHandlerInvokerUtil { public static void invokeChannelRegisteredNow(ChannelHandlerContext ctx) { try { ctx.handler().channelRegistered(ctx); } catch (Throwable t) { notifyHandlerException(ctx, t); } } }
private static int skipFlags0(Class<? extends ChannelHandler> handlerType) { int flags = 0; try { if (handlerType.getMethod( "handlerAdded", ChannelHandlerContext.class).isAnnotationPresent(Skip.class)) { flags |= MASK_HANDLER_ADDED; } if (handlerType.getMethod( "handlerRemoved", ChannelHandlerContext.class).isAnnotationPresent(Skip.class)) { flags |= MASK_HANDLER_REMOVED; } if (handlerType.getMethod( "exceptionCaught", ChannelHandlerContext.class, Throwable.class).isAnnotationPresent(Skip.class)) { flags |= MASK_EXCEPTION_CAUGHT; } if (handlerType.getMethod( "channelRegistered", ChannelHandlerContext.class).isAnnotationPresent(Skip.class)) { flags |= MASK_CHANNEL_REGISTERED; } }
ChannelHandler接口定义了如何处理inbound和outbond事件的方法,是职责链节点的具体实现,也是业务代码编写地方。Netty抽象了Pipeline这个职责链,将底层IO处理和业务处理进行了隔离,使用户可以关注与业务逻辑的实现。
public interface ChannelHandler { /////////////////////////////////// // Inbound event handler methods // /////////////////////////////////// void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception; void channelRegistered(ChannelHandlerContext ctx) throws Exception; // Outbound event handler methods // //////////////////////////////////// void bind(ChannelHandlerContext ctx, SocketAddress localAddress, ChannelPromise promise) throws Exception; void connect( ChannelHandlerContext ctx, SocketAddress remoteAddress, SocketAddress localAddress, ChannelPromise promise) throws Exception; }
Unsafe定义了实际IO处理的接口,它的含义不是说它的方法是不安全的,而是说它的接口是给框架本身调用的,不要暴露给业务层调用。
Unsafe的最底层实现类采用了模板方法模式,NioMessageUnsafe绑定到了NioServerSocketChannel,NioByteUnsafe绑定到NioSocketChannel,
最终的IO读写方法实现在NioServerSocketChannel和NioByteUnsafe中,调用了Java的ServerSocketChannel和SocketChannel来实现。
interface Unsafe { ChannelHandlerInvoker invoker(); SocketAddress localAddress(); SocketAddress remoteAddress(); void register(ChannelPromise promise); void bind(SocketAddress localAddress, ChannelPromise promise); void connect(SocketAddress remoteAddress, SocketAddress localAddress, ChannelPromise promise); void disconnect(ChannelPromise promise); void close(ChannelPromise promise); void closeForcibly(); void beginRead(); void write(Object msg, ChannelPromise promise); void flush(); ChannelPromise voidPromise(); ChannelOutboundBuffer outboundBuffer(); } <pre name="code" class="java">private final class NioByteUnsafe extends AbstractNioUnsafe {