Netty源码阅读5——Pipeline

Posted by 皮皮潘 on 12-05,2021

Pipeline是一个链式结构,pipeline中的每个节点是一个ChannelHandlerContext对象,每个context节点保存了它包裹的执行器 ChannelHandler ,节点之间通过双向链表连接

在创建一个Pipeline的时候会创建对应的HeadContext以及TailContext去处理边缘的事件,所有用户定义的Handler都会夹在Head和Tail中间

在调用addXXX去增加一个ChannelHandler的时候其核心代码如下:

public final ChannelPipeline addLast(EventExecutorGroup group, String name, ChannelHandler handler) {
    final AbstractChannelHandlerContext newCtx;
    synchronized (this) {
        // 1.检查是否有重复handler
        checkMultiplicity(handler);
        // 2.创建节点
        newCtx = newContext(group, filterName(name, handler), handler);
        // 3.添加节点
        addLast0(newCtx);
    }
   
    // 4.回调用户方法
    callHandlerAdded0(handler);
    return this;
}

其中简单地使用synchronized防止多线程并发操作双向链表

  1. 检查是否有重复的handler:netty使用一个成员变量added标识一个channel是否已经添加,如果当前要添加的Handler是非共享的,并且已经添加过(添加到别的Pipeline中去过),那就抛出异常,否则,标识该handler已经添加

  2. 创建DefaultChannelHandlerContext并包含对应的Handler

  3. 添加节点就是一个简单地双向链表插入操作

  4. 通过调用ctx.handler().handerAdded(ctx)来回调handlerAdded方法

在事件处理以及传递过程中,inBound事件从head节点传播到tail节点,outBound事件从tail节点传播到head节点,最后都会交由边缘的Head和Tail绑定的Unsafe去处理底层操作,NioServerSocketChannel对应NioMessageUnsafe, NioSocketChannel对应NioByteUnsafe,除此之外异常传播会通过调用notifyHandlerException(t)往后传播,而且不分inbound还是outbound节点,不像outBound事件一样会往前传播,因此ExceptionHandler一般都放在末尾