Netty-处理器链

归档


处理器链

  • 每个信道都有一个流水线 ChannelPipeline
    • 默认实现类为 DefaultChannelPipeline
  • 默认流水线内部封装上下文 ChannelHandlerContext
    • 上下文默认实现类为 DefaultChannelHandlerContext
    • 相当于是双向链表(节点数据为处理器 ChannelHandler

DefaultChannelPipeline

/*** 默认信道流水线 */
public class DefaultChannelPipeline implements ChannelPipeline {
    final HeadContext head; // 头节点
    final TailContext tail; // 尾节点
    private final Channel channel; // 信道

    // 构造器(在创建信道时调用)
    protected DefaultChannelPipeline(Channel channel) {
        this.channel = ObjectUtil.checkNotNull(channel, "channel");
        ...

        tail = new TailContext(this);
        head = new HeadContext(this);

        head.next = tail;
        tail.prev = head;
    }

    // sign_demo_010 添加到尾部
    @Override
    public final ChannelPipeline addLast(String name, ChannelHandler handler) {
        return addLast(null, name, handler); // sign_m_001 添加到尾部并设置线程
    }

    /**
     * sign_m_001 添加到尾部并设置线程
     * 
     * group 为空则不设置线程,不为空则提取一个线程设置给节点
     */
    @Override 
    public final ChannelPipeline addLast(EventExecutorGroup group, String name, ChannelHandler handler) {
        final AbstractChannelHandlerContext newCtx;
        synchronized (this) {
            /**
             * 校验 handler 是否重复添加。
             * 如果 handler 需要被重复添加到流水线,则需要加 @Sharable 注解
             */
            checkMultiplicity(handler);

            newCtx = newContext(group, filterName(name, handler), handler); // sign_m_002 创建上下文节点

            addLast0(newCtx); // sign_m_003 添加到尾部

            ... // 未注册挂起与异步调用钩子函数处理
        }
        callHandlerAdded0(newCtx); // sign_m_004 回调 handler 钩子函数 handlerAdded(ctx)
        return this;
    }

    // sign_m_002 创建上下文节点
    private AbstractChannelHandlerContext newContext(EventExecutorGroup group, String name, ChannelHandler handler) {
        return new DefaultChannelHandlerContext(this, childExecutor(group), name, handler); // sign_m_010 将 handler 封装到节点里
    }

    // sign_m_003 添加到尾部(但在尾节点之前)
    private void addLast0(AbstractChannelHandlerContext newCtx) {
        /**
         * 相当于链结构由:
         *   ... <-> prev <-> tail
         * 变成:
         *   ... <-> prev <-> newCtx <-> tail
         */
        AbstractChannelHandlerContext prev = tail.prev;
        newCtx.prev = prev;
        newCtx.next = tail;
        prev.next = newCtx;
        tail.prev = newCtx;
    }

    // sign_m_004 回调 handler 钩子函数 handlerAdded(ctx)
    private void callHandlerAdded0(final AbstractChannelHandlerContext ctx) {
        try {
            ctx.callHandlerAdded();
        } ... // catch
    }
}

DefaultChannelHandlerContext

  • io.netty.channel.DefaultChannelHandlerContext
/*** 默认处理器上下文(相当于双链表节点) */
final class DefaultChannelHandlerContext extends AbstractChannelHandlerContext {
    private final ChannelHandler handler; // 封装的处理器

    // sign_m_010 将 handler 封装到节点里
    DefaultChannelHandlerContext(
            DefaultChannelPipeline pipeline, EventExecutor executor, String name, ChannelHandler handler
    ) {
        // executor 相当于线程
        super(pipeline, executor, name, handler.getClass()); // sign_m_020
        this.handler = handler;
    }

    @Override
    public ChannelHandler handler() {
        return handler;
    }
}
  • io.netty.channel.AbstractChannelHandlerContext
// 上下文节点父类
abstract class AbstractChannelHandlerContext implements ChannelHandlerContext, ResourceLeakHint {
    volatile AbstractChannelHandlerContext next;    // 下一个节点
    volatile AbstractChannelHandlerContext prev;    // 上一个节点
    private final DefaultChannelPipeline pipeline;  // 用于反查流水线
    private final String name; // 如果未指定,则默认用处理器类简名 + "#0" 进行赋值
    final EventExecutor executor;

    // sign_m_020
    AbstractChannelHandlerContext(DefaultChannelPipeline pipeline, EventExecutor executor,
                                  String name, Class<? extends ChannelHandler> handlerClass
    ) {
        this.name = ObjectUtil.checkNotNull(name, "name");
        this.pipeline = pipeline;
        this.executor = executor;
        ... // 其他设置
    }

    /**
     * sign_f_001 执行线程
     * 
     * 用于执行当前处理器的相关方法,
     * 如果为空(未指定),则用信道的线程执行。
     */
    @Override
    public EventExecutor executor() {
        if (executor == null) {
            return channel().eventLoop();
        } else {
            return executor;
        }
    }
}

读流程

/*** 默认信道流水线 */
public class DefaultChannelPipeline implements ChannelPipeline {
    // sign_o_010 发送读取的字节
    @Override
    public final ChannelPipeline fireChannelRead(Object msg) {
        AbstractChannelHandlerContext.invokeChannelRead(head, msg);     // sign_m_101 使用头节点读
        return this;
    }

    // sign_o_020 发送读取完成事件
    @Override
    public final ChannelPipeline fireChannelReadComplete() {
        AbstractChannelHandlerContext.invokeChannelReadComplete(head);  // sign_m_110 从头节点开始
        return this;
    }

    /*** 头节点 */
    final class HeadContext extends AbstractChannelHandlerContext
                            implements ChannelOutboundHandler, ChannelInboundHandler
    {
        // sign_m_130 读
        @Override
        public void channelRead(ChannelHandlerContext ctx, Object msg) {
            ctx.fireChannelRead(msg); // sign_m_131 上下文读
        }
    }
}
  • io.netty.channel.AbstractChannelHandlerContext
abstract class AbstractChannelHandlerContext implements ChannelHandlerContext, ResourceLeakHint {
    // sign_m_101 开启读调用
    static void invokeChannelRead(final AbstractChannelHandlerContext next, Object msg) {
        final Object m = next.pipeline.touch(ObjectUtil.checkNotNull(msg, "msg"), next);
        EventExecutor executor = next.executor();   // sign_f_001
        if (executor.inEventLoop()) {
            next.invokeChannelRead(m);              // sign_i_102 使用(当前类的)实例方法进行读
        } else {
            ... // 用给定的线程执行 invokeChannelRead(m) 方法
        }
    }

    // sign_i_102 读处理
    private void invokeChannelRead(Object msg) {
        if (invokeHandler()) {
            try {
                // see https://bugs.openjdk.org/browse/JDK-8180450
                final ChannelHandler handler = handler();
                final DefaultChannelPipeline.HeadContext headContext = pipeline.head;
                if (handler == headContext) {
                    headContext.channelRead(this, msg); // sign_m_130 头节点处理读
                } else if (handler instanceof ChannelDuplexHandler) {
                    ((ChannelDuplexHandler) handler).channelRead(this, msg);
                } else {
                    /**
                     * 调用对应的入站处理器进行读取
                     * handler 实现的方法一般会调用 ctx.fireChannelRead(msg) - sign_m_131 进入链式传递
                     */
                    ((ChannelInboundHandler) handler).channelRead(this, msg);
                }
            } ... // catch
        } ... // else 
    }

    // sign_m_110 开启调用
    static void invokeChannelReadComplete(final AbstractChannelHandlerContext next) {
        EventExecutor executor = next.executor();   // sign_f_001
        if (executor.inEventLoop()) {
            next.invokeChannelReadComplete();       // 当前类的实例方法。具体实现略...
        } else {
            ... // 相当于用给定的线程执行 invokeChannelReadComplete() 方法
        }
    }

    // sign_m_131 读处理(链式调用处理)
    @Override
    public ChannelHandlerContext fireChannelRead(final Object msg) {
        /**
         * sign_m_132 findContextInbound 查找下一个节点
         * sign_m_101 invokeChannelRead  开启读调用
         */
        invokeChannelRead(findContextInbound(MASK_CHANNEL_READ), msg);
        return this;
    }

    // sign_m_132 查找链表上的入站处理器节点
    private AbstractChannelHandlerContext findContextInbound(int mask) {
        AbstractChannelHandlerContext ctx = this;
        EventExecutor currentExecutor = executor();
        do {
            ctx = ctx.next;
        } while (skipContext(ctx, currentExecutor, mask, MASK_ONLY_INBOUND)); // sign_m_301 判断是否跳过此 ctx
        return ctx;
    }
}

写流程

    // sign_u_001 信道写入消息
    @Override
    public ChannelFuture write(Object msg) {
        return pipeline.write(msg); // sign_m_201 流水线写入消息
    }
  • io.netty.channel.DefaultChannelPipeline
/*** 默认信道流水线 */
public class DefaultChannelPipeline implements ChannelPipeline {
    // sign_m_201 写入消息
    @Override
    public final ChannelFuture write(Object msg) {
        return tail.write(msg); // sign_m_210 从尾节点开始写入
    }
}
  • io.netty.channel.AbstractChannelHandlerContext
abstract class AbstractChannelHandlerContext implements ChannelHandlerContext, ResourceLeakHint {
    // sign_m_210 写入消息
    @Override
    public ChannelFuture write(Object msg) {
        return write(msg, newPromise()); // sign_m_211 写入消息
    }

    // sign_m_211 写入消息
    @Override
    public ChannelFuture write(final Object msg, final ChannelPromise promise) {
        write(msg, false, promise); // sign_m_212 写入消息
        return promise;
    }

    // sign_m_212 写入消息
    private void write(Object msg, boolean flush, ChannelPromise promise) {
        ... // 省略校验处理

        final AbstractChannelHandlerContext next = findContextOutbound( // 查找下一个出站处理器
            flush ? (MASK_WRITE | MASK_FLUSH) : MASK_WRITE
        );
        final Object m = pipeline.touch(msg, next);
        EventExecutor executor = next.executor();
        if (executor.inEventLoop()) {
            if (flush) {
                next.invokeWriteAndFlush(m, promise);   // 写入并推送
            } else {
                next.invokeWrite(m, promise);           // sign_m_213 仅写入
            }
        } else {
            ... // 异步执行
        }
    }

    // sign_m_213 调用写入
    void invokeWrite(Object msg, ChannelPromise promise) {
        if (invokeHandler()) {
            invokeWrite0(msg, promise); // sign_m_214 调用写入
        } ... // else
    }

    // sign_m_214 调用写入
    private void invokeWrite0(Object msg, ChannelPromise promise) {
        try {
            // see https://bugs.openjdk.org/browse/JDK-8180450
            final ChannelHandler handler = handler();
            final DefaultChannelPipeline.HeadContext headContext = pipeline.head;
            if (handler == headContext) {
                headContext.write(this, msg, promise); // sign_o_030 头节点写入消息
            } else if (handler instanceof ChannelDuplexHandler) {
                ((ChannelDuplexHandler) handler).write(this, msg, promise);
            } else {
                /**
                 * 调用对应的出站处理器进行写入
                 * handler 实现的方法一般会调用 ctx.write(msg, promise); - sign_m_211 进入链式传递
                 */
                ((ChannelOutboundHandler) handler).write(this, msg, promise);
            }
        } ... // catch
    }
}

处理器回调函数逻辑

        // sign_m_201
        private void register0(ChannelPromise promise) {
            try {
                ... // 略
                pipeline.invokeHandlerAddedIfNeeded();  // 回调被添加到流水线的方法
                safeSetSuccess(promise);
                pipeline.fireChannelRegistered();       // 回调信道被添加到事件轮循的方法
                ... // 略
            } ... // catch
        }

@Skip-原理

  • io.netty.channel.AbstractChannelHandlerContext
abstract class AbstractChannelHandlerContext implements ChannelHandlerContext, ResourceLeakHint {
    private final int executionMask; // 执行的掩码

    AbstractChannelHandlerContext(DefaultChannelPipeline pipeline, EventExecutor executor,
                                  String name, Class<? extends ChannelHandler> handlerClass
    ) {
        this.executionMask = mask(handlerClass); // sign_m_150 根据类计算掩码
    }

    // sign_m_301 判断是否跳过此 ctx
    private static boolean skipContext(
            AbstractChannelHandlerContext ctx, EventExecutor currentExecutor, int mask, int onlyMask
    ) {
        // 与当前上下文设置的掩码不一致,则跳过
        return (ctx.executionMask & (onlyMask | mask)) == 0 ||
                (ctx.executor() == currentExecutor && (ctx.executionMask & mask) == 0);
    }
}
  • io.netty.channel.ChannelHandlerMask
// 掩码帮助类
public final class ChannelHandlerMask {
    // sign_m_150 根据类计算掩码
    static int mask(Class<? extends ChannelHandler> clazz) {
        Map<Class<? extends ChannelHandler>, Integer> cache = MASKS.get();
        Integer mask = cache.get(clazz);
        if (mask == null) {
            mask = mask0(clazz); // sign_i_151 计算掩码
            cache.put(clazz, mask);
        }
        return mask;
    }

    // sign_i_151 计算掩码
    private static int mask0(Class<? extends ChannelHandler> handlerType) {
        int mask = MASK_EXCEPTION_CAUGHT;
        try {
            if (ChannelInboundHandler.class.isAssignableFrom(handlerType)) {
                mask |= MASK_ALL_INBOUND;

                /**
                 * sign_i_152 判断方法是否应跳过。
                 * 如果 isSkippable() 返回 true,则表示跳过,
                 * 掩码则取反 (~)
                 */
                if (isSkippable(handlerType, "channelRegistered", ChannelHandlerContext.class)) {
                    mask &= ~MASK_CHANNEL_REGISTERED;
                }
                ... // 省略 channelUnregistered channelActive channelInactive
                ... // 省略 channelRead channelReadComplete channelWritabilityChanged userEventTriggered
            }

            if (ChannelOutboundHandler.class.isAssignableFrom(handlerType)) {
                mask |= MASK_ALL_OUTBOUND;

                ... // 省略 bind connect disconnect close deregister
                ... // 省略 read write flush
            }

            ... // 省略 exceptionCaught
        } ... // catch

        return mask;
    }

    // sign_i_152 判断方法是否应跳过
    private static boolean isSkippable(
            final Class<?> handlerType, final String methodName, final Class<?>... paramTypes
    ) throws Exception {
        return AccessController.doPrivileged(new PrivilegedExceptionAction<Boolean>() {
            @Override
            public Boolean run() throws Exception {
                Method m;
                try {
                    m = handlerType.getMethod(methodName, paramTypes); // 查找要判断的方法
                } catch (NoSuchMethodException e) {
                    ... // 省略日志输出
                    return false; // 没有此方法,则不跳过
                }
                return m.isAnnotationPresent(Skip.class); // 判断此方法是否有 @Skip 注解:有的话,则跳过
            }
        });
    }

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值