netty的pipeline寻找下一个节点的原理解读

netty在pipeline中寻找下一个处理节点的方法主要依靠位运算的方式,根据mask标记来进行查找

Handler加入pipeline,给executionMask属性赋值

executionMask代表handler实现了哪几个处理方法

Handler加入pipeline最终会封装成DefaultChannelHandlerContext

DefaultChannelHandlerContext的构造函数中,对handler使用解析,查看他实现了哪几个方法

AbstractChannelHandlerContext(DefaultChannelPipeline pipeline, EventExecutor executor,
                                  String name, Class<? extends ChannelHandler> handlerClass) {
    this.name = ObjectUtil.checkNotNull(name, "name");
    this.pipeline = pipeline;
    this.executor = executor;
    // 保存 入站处理、出站处理、异常处理的 标志位
    // 替代了老版本里边 inbound ,outbound 标准位
    // 细粒度的 处理操作 标志位
    this.executionMask = mask(handlerClass);
    // Its ordered if its driven by the EventLoop or the given Executor is an instanceof OrderedEventExecutor.
    ordered = executor == null || executor instanceof OrderedEventExecutor;
}

这里需要解释ChannelHandlerMask类,它的主要作用是对出站处理,入站处理,异常处理的方法,使用位运算进行了映射

异常处理的映射

映射属性字段 对应的方法
MASK_EXCEPTION_CAUGHT = 1 exceptionCaught

入站处理的映射

映射属性字段 对应的方法
MASK_CHANNEL_REGISTERED = 1 << 1 channelRegistered
MASK_CHANNEL_UNREGISTERED = 1 << 2 channelUnregistered
MASK_CHANNEL_ACTIVE = 1 << 3 channelActive
MASK_CHANNEL_INACTIVE = 1 << 4 channelInactive
MASK_CHANNEL_READ = 1 << 5 channelRead
MASK_CHANNEL_READ_COMPLETE = 1 << 6 channelReadComplete
MASK_USER_EVENT_TRIGGERED = 1 << 7 userEventTriggered
MASK_CHANNEL_WRITABILITY_CHANGED = 1 << 8 channelWritabilityChanged

出站处理的映射

映射属性字段 对应的方法
MASK_BIND = 1 << 9 bind
MASK_CONNECT = 1 << 10 connect
MASK_DISCONNECT = 1 << 11 disconnect
MASK_CLOSE = 1 << 12 close
MASK_DEREGISTER = 1 << 13 deregister
MASK_READ = 1 << 14 read
MASK_WRITE = 1 << 15 write
MASK_FLUSH = 1 << 16 flush

合并处理映射

映射属性字段 对应的方法
MASK_ONLY_INBOUND 所有的入站处理操作进行或运算
MASK_ONLY_OUTBOUND 所有的出站处理操作进行或运算
MASK_ALL_INBOUND 所有入站处理操作+异常
MASK_ALL_OUTBOUND 所有出站处理操作+异常

对handler类进行解析,组装当前类实现了哪几个方法的mask标记

private static int mask0(Class<? extends ChannelHandler> handlerType) {
    // mask 存储 处理器中 最终实现 出站处理、入站处理、异常的能力
    int mask = MASK_EXCEPTION_CAUGHT;
    try {
        if (ChannelInboundHandler.class.isAssignableFrom(handlerType)) {
            // 先 给到 所有的出站处理器的能力
            mask |= MASK_ALL_INBOUND;

            if (isSkippable(handlerType, "channelRegistered", ChannelHandlerContext.class)) {
                // 去掉 CHANNEL_REGISTERED 入站处理
                mask &= ~MASK_CHANNEL_REGISTERED;
            }
            if (isSkippable(handlerType, "channelUnregistered", ChannelHandlerContext.class)) {
                mask &= ~MASK_CHANNEL_UNREGISTERED;
            }
            if (isSkippable(handlerType, "channelActive", ChannelHandlerContext.class)) {
                mask &= ~MASK_CHANNEL_ACTIVE;
            }
            if (isSkippable(handlerType, "channelInactive", ChannelHandlerContext.class)) {
                mask &= ~MASK_CHANNEL_INACTIVE;
            }
            if (isSkippable(handlerType, "channelRead", ChannelHandlerContext.class, Object.class)) {
                mask &= ~MASK_CHANNEL_READ;
            }
            if (isSkippable(handlerType, "channelReadComplete", ChannelHandlerContext.class)) {
                mask &= ~MASK_CHANNEL_READ_COMPLETE;
            }
            if (isSkippable(handlerType, "channelWritabilityChanged", ChannelHandlerContext.class)) {
                mask &= ~MASK_CHANNEL_WRITABILITY_CHANGED;
            }
            if (isSkippable(handlerType, "userEventTriggered", ChannelHandlerContext.class, Object.class)) {
                mask &= ~MASK_USER_EVENT_TRIGGERED;
            }
        }

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

            if (isSkippable(handlerType, "bind", ChannelHandlerContext.class,
                            SocketAddress.class, ChannelPromise.class)) {
                mask &= ~MASK_BIND;
            }
            if (isSkippable(handlerType, "connect", ChannelHandlerContext.class, SocketAddress.class,
                            SocketAddress.class, ChannelPromise.class)) {
                mask &= ~MASK_CONNECT;
            }
            if (isSkippable(handlerType, "disconnect", ChannelHandlerContext.class, ChannelPromise.class)) {
                mask &= ~MASK_DISCONNECT;
            }
            if (isSkippable(handlerType, "close", ChannelHandlerContext.class, ChannelPromise.class)) {
                mask &= ~MASK_CLOSE;
            }
            if (isSkippable(handlerType, "deregister", ChannelHandlerContext.class, ChannelPromise.class)) {
                mask &= ~MASK_DEREGISTER;
            }
            if (isSkippable(handlerType, "read", ChannelHandlerContext.class)) {
                mask &= ~MASK_READ;
            }
            if (isSkippable(handlerType, "write", ChannelHandlerContext.class,
                            Object.class, ChannelPromise.class)) {
                mask &= ~MASK_WRITE;
            }
            if (isSkippable(handlerType, "flush", ChannelHandlerContext.class)) {
                mask &= ~MASK_FLUSH;
            }
        }

        if (isSkippable(handlerType, "exceptionCaught", ChannelHandlerContext.class, Throwable.class)) {
            mask &= ~MASK_EXCEPTION_CAUGHT;
        }
    } catch (Exception e) {
        // Should never reach here.
        PlatformDependent.throwException(e);
    }

    return mask;
}

/**
 * 判断当前handler是否存在以methodName命名的方法
 * @param handlerType 当前handler的class
 * @param methodName 要判断的方法名
 * @param paramTypes 要判断的方法参数
 * @return 存在@Skip为true,不存在@Skip为false
 */
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) {
                if (logger.isDebugEnabled()) {
                    logger.debug(
                        "Class {} missing method {}, assume we can not skip execution", handlerType, methodName, e);
                }
                return false;
            }

            // @Skip的作用,就是标志着当前类是否被重写
            // 如果方法存在@Skip,那么就代表当前类没有被重写
            // 如果方法没有存在@Skip,那么就代表当前类被重写
            return m != null && m.isAnnotationPresent(Skip.class);
        }
    });
}

mask0方法总结

channelRegistered方法为例

如果一个handler实现了channelRegistered的方法,使用**isSkippable方法进行判断
因为实现了channelRegistered,那么父类的注解失效,即当前类上没有Skip注解,那么就将mask代表着
channelRegistered**方法的位置为1

ChannelInboundHandlerAdapter的入站处理方法和ChannelOutboundHandlerAdapter的出站处理方法都被Skip注解进行标记

pipeline如何查找下一个实现了channelRegistered的处理器?

pipeline会调用到**io.netty.channel.AbstractChannelHandlerContext#fireChannelRegistered**方法

@Override
public ChannelHandlerContext fireChannelRegistered() {
    // 将channelRegistered的标志位传入
    invokeChannelRegistered(findContextInbound(MASK_CHANNEL_REGISTERED));
    return this;
}

AbstractChannelHandlerContext#findContextInbound方法整理

/**
 *
 * @param mask 表示要查找的 对应的操作位
 * @return 查找到的handler
 */
private AbstractChannelHandlerContext findContextInbound(int mask) {
    AbstractChannelHandlerContext ctx = this;
    EventExecutor currentExecutor = executor();
    do {
        ctx = ctx.next;
    } while (skipContext(ctx, currentExecutor, mask, MASK_ONLY_INBOUND));
    return ctx;
}

AbstractChannelHandlerContext#skipContext方法梳理

/**
 * 这个方法返回 true,表示跳过这个 ctx,继续从 流水线 中查找下一个。
 * @param ctx handler对应pipeline中的节点
 * @param currentExecutor 当前处理任务的执行器
 * @param mask 判断handler实现的方法标志
 * @param onlyMask 表示大的方向,是出站,还是 入站
 * @return true表示跳过
 */
private static boolean skipContext(
    AbstractChannelHandlerContext ctx, EventExecutor currentExecutor, int mask, int onlyMask) {
    // (onlyMask | mask)主要处理的是异常方法的判断
    // 如果handler实现了mask代表的方法,那么notSameType就为false
    boolean notSameType = (ctx.executionMask & (onlyMask | mask)) == 0;

    // 当前线程的时候,才会考虑是否跳过 ctx,目标处理器的线程不是当前线程,也跳过
    // 只有当 ctx.executor() 是 currentExecutor  当前线程的时候,才会考虑是否跳过 ctx,因为我们要保证事件处理的顺序。
    boolean sameThreadAndNotDefined = ctx.executor() == currentExecutor && (ctx.executionMask & mask) == 0;

    return notSameType || sameThreadAndNotDefined;
}

你可能感兴趣的:(java)