四Netty组件类--5ChannelHandlerContext

四Netty组件类--5ChannelHandlerContext

17.5 ChannelHandlerContext

17.5.1 ChannelHandlerMask

对事件的inbound和outbound定义

final class ChannelHandlerMask {
    private static final InternalLogger logger = InternalLoggerFactory.getInstance(ChannelHandlerMask.class);

    // Using to mask which methods must be called for a ChannelHandler.
    static final int MASK_EXCEPTION_CAUGHT = 1;
    static final int MASK_CHANNEL_REGISTERED = 1 << 1;
    static final int MASK_CHANNEL_UNREGISTERED = 1 << 2;
    static final int MASK_CHANNEL_ACTIVE = 1 << 3;
    static final int MASK_CHANNEL_INACTIVE = 1 << 4;
    static final int MASK_CHANNEL_READ = 1 << 5;
    static final int MASK_CHANNEL_READ_COMPLETE = 1 << 6;
    static final int MASK_USER_EVENT_TRIGGERED = 1 << 7;
    static final int MASK_CHANNEL_WRITABILITY_CHANGED = 1 << 8;
    static final int MASK_BIND = 1 << 9;
    static final int MASK_CONNECT = 1 << 10;
    static final int MASK_DISCONNECT = 1 << 11;
    static final int MASK_CLOSE = 1 << 12;
    static final int MASK_DEREGISTER = 1 << 13;
    static final int MASK_READ = 1 << 14;
    static final int MASK_WRITE = 1 << 15;
    static final int MASK_FLUSH = 1 << 16;

    static final int MASK_ONLY_INBOUND =  MASK_CHANNEL_REGISTERED |
            MASK_CHANNEL_UNREGISTERED | MASK_CHANNEL_ACTIVE | MASK_CHANNEL_INACTIVE | MASK_CHANNEL_READ |
            MASK_CHANNEL_READ_COMPLETE | MASK_USER_EVENT_TRIGGERED | MASK_CHANNEL_WRITABILITY_CHANGED;
    private static final int MASK_ALL_INBOUND = MASK_EXCEPTION_CAUGHT | MASK_ONLY_INBOUND;
    static final int MASK_ONLY_OUTBOUND =  MASK_BIND | MASK_CONNECT | MASK_DISCONNECT |
            MASK_CLOSE | MASK_DEREGISTER | MASK_READ | MASK_WRITE | MASK_FLUSH;
    private static final int MASK_ALL_OUTBOUND = MASK_EXCEPTION_CAUGHT | MASK_ONLY_OUTBOUND;

    private static final FastThreadLocal<Map<Class<? extends ChannelHandler>, Integer>> MASKS =
            new FastThreadLocal<Map<Class<? extends ChannelHandler>, Integer>>() {
                @Override
                protected Map<Class<? extends ChannelHandler>, Integer> initialValue() {
                    return new WeakHashMap<Class<? extends ChannelHandler>, Integer>(32);
                }
            };

事件定义:

InBound:exceptionCaught、registered、ungistered、active、inactive、read、read_complete、wribability_changed

OutBound: connect、disconnect、close、deregister、read、write、flush

17.5.2 ChannelHandlerContext主要继承关系类图(pipeline上handler链式调用)

ChannelHandlerContext实现ChannelInboundInvoker和ChannelOutboundInvoker(这两个invoker分别是inbound和outbound的方法的调用,用来先执行对应的方法并调用channel.channePipeline链上下一个channelHandler对应的方法,因此是链式调用的实现),因此,context也具有链式调用的关键。

image-20221129114153722

HeadContext和TailContext既属于channelHandler,又属于ChannelHandlerContext。

该类是真正保存在pipeline中的节点,是对channelHandler的包装类。其内包装上下文信息,如prev、next等pipeline中链式处理节点。

image-20221129135827089

17.5.2.1 AbstractChannelHandlerContext

AbstractChannelHandlerContext中属性和构造函数如下:

abstract class AbstractChannelHandlerContext implements ChannelHandlerContext, ResourceLeakHint {

    private static final AtomicIntegerFieldUpdater<AbstractChannelHandlerContext> HANDLER_STATE_UPDATER =
            AtomicIntegerFieldUpdater.newUpdater(AbstractChannelHandlerContext.class, "handlerState");

/**…………………………………………………代表ChannelHandler#handlerAdded(ChannelHandlerContext)是否被执行的状态………………………………………………………… */
    /**
     * {@link ChannelHandler#handlerAdded(ChannelHandlerContext)} is about to be called.
     */
    private static final int ADD_PENDING = 1;
    /**
     * {@link ChannelHandler#handlerAdded(ChannelHandlerContext)} was called.
     */
    private static final int ADD_COMPLETE = 2;
    /**
     * {@link ChannelHandler#handlerRemoved(ChannelHandlerContext)} was called.
     */
    private static final int REMOVE_COMPLETE = 3;
    /**
     * Neither {@link ChannelHandler#handlerAdded(ChannelHandlerContext)}
     * nor {@link ChannelHandler#handlerRemoved(ChannelHandlerContext)} was called.
     */
    private static final int INIT = 0;
    private volatile int handlerState = INIT; //代表上述ChannelHandler#handlerAdded(ChannelHandlerContext)是否被执行的状态

  
    volatile AbstractChannelHandlerContext next;
    volatile AbstractChannelHandlerContext prev;
    private final DefaultChannelPipeline pipeline; //context绑定的DefaultChannelPipeline
    private final String name;
    private final boolean ordered;
    //该executionMask用来指定当前channelHandlerContext经过位运算需要跳过的inbound和outbound的方法
    private final int executionMask;

  
    final EventExecutor executor; //context绑定的EventExecutor
    private ChannelFuture succeededFuture;

    // Lazily instantiated tasks used to trigger events to a handler with different executor.
    // There is no need to make this volatile as at worse it will just create a few more instances then needed.
    private Tasks invokeTasks;

  	//构造函数
    AbstractChannelHandlerContext(DefaultChannelPipeline pipeline, EventExecutor executor,
                                  String name, Class<? extends ChannelHandler> handlerClass) {
        this.name = ObjectUtil.checkNotNull(name, "name");
        this.pipeline = pipeline;
        this.executor = executor;
        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;
    }

image-20221129163108696

invokeXXX方法,是AbstractChannelHandlerContext中的方法,用来调用context(也就是inbound/outboundInvoker内的方法)。

17.5.3 ChannelOutboundInvoker/ChannelInboundInvoker

image-20221129181418968

invoker是对channel的inbound和outbound的调用,因此也是实现链式调用的关键类。两个实现类channelPipeline和channelHandlerContext,分别实现in/out方法,也就具有链式调用的功能。

17.5.3.1 ChannelOutboundInvoker

image-20221129144131764

invoker内方法,会执行相应的outbound操作,并在操作完成后,调用channel.channelPipelin上的下一个ChannelOutboundHandler上对应的方法被调用,实现pipeline上handlerContext的链式调用。

image-20221129142500909

public interface ChannelOutboundInvoker {

    /**
     请求绑定到给定的socketAddress上,并在操作完成后返回channelFuture作为通知对象。
     这个方法,会使channel上的pipeline中的下一个ChannelOutboundHandler的bind(ChannelHandlerContext, SocketAddress, ChannelPromise)方法被调用
     */
    ChannelFuture bind(SocketAddress localAddress);

ChannelOutboundInvoker的方法,都返回ChannelFuture对象。

17.5.3.2 ChannelInboundInvoker

image-20221129144136584

invoker内方法,会执行相应的inbound操作,并在操作完成后,调用channel.channelPipelin上的下一个ChannelInboundHandler上对应的方法被调用,实现pipeline上handlerContext的链式调用。

inboundInvoker上的方法都是以fireXXX命名。

public interface ChannelInboundInvoker {

    /**
     * 注册channel到它的eventloop上
     *这个方法,会使channel上的pipeline中的下一个ChannelInboundHandler的channelRegistered(ChannelHandlerContext)方法被调用
     */
    ChannelInboundInvoker fireChannelRegistered();

image-20221129143324162

17.5.3.3 AbstractChannelHandlerContext.fireChannelRead流程

以fireChannelRean为例:

channelHandlerContext的对应的方法fireXXX——>Invoker对象上的invokeXXX方法——>i调用invoker的工具类util上的invokXXXnow方法——>channelhandler.channelRead()对应的方法。这是完整的pipeline上的事件的传递和执行流程。

如果需要触发事件,直接调用channelHandlerContext中的方法。

TAG0.0 fireChannelRead---channelInboundInvoker的方法

首先,AbstractChannelHandlerContext.fireChannelRead方法调用,触发事件

AbstractChannelHandlerContext
  
    @Override
    public ChannelHandlerContext fireChannelRead(final Object msg) {
//TAG1 findContextInbound
//TAG2 invokeChannelRead
        invokeChannelRead(findContextInbound(MASK_CHANNEL_READ), msg);
        return this;
    }
TAG1 findContextInbound

从pipeline中找出对应的channel-read的inboundChannelHandler对应的context。

AbstractChannelHandlerContext
 			
 	//找到pipeline中inbound的处理器对应的context
  private AbstractChannelHandlerContext findContextInbound(int mask) {
        AbstractChannelHandlerContext ctx = this;
      	//返回当前AbstractChannelHandlerContext.executor或者channel().eventLoop()对象
        EventExecutor currentExecutor = executor();
        do {
            ctx = ctx.next;
        } 
  //TAG1.1 skipContext
  while (skipContext(ctx, currentExecutor, mask, MASK_ONLY_INBOUND));
        return ctx;
    }

这里的逻辑:do-while操作,遍历ctx链,如果当前ctx不需要跳过skipContext(也就是当前ctx的执行executionMask,不包含在所需要操作的mask或者MASK_ONLY_INBOUND时,返回true,进行下一个循环,当需要执行时,就false,终止循环),就是当前AbstractChannelHandlerContext支持事件执行,就筛选出来---------------------------因此,就是寻找inbound中mask事件的context。

TAG1.1 skipContext

对于此处处理channel.read的事件,mask为MASK_CHANNEL_READ = 1 << 5;onlyMask为所有的inbound操作。

  ChannelHandlerMask  
	static final int MASK_ONLY_INBOUND =  MASK_CHANNEL_REGISTERED |
            MASK_CHANNEL_UNREGISTERED | MASK_CHANNEL_ACTIVE | MASK_CHANNEL_INACTIVE | MASK_CHANNEL_READ |
            MASK_CHANNEL_READ_COMPLETE | MASK_USER_EVENT_TRIGGERED | MASK_CHANNEL_WRITABILITY_CHANGED;

AbstractChannelHandlerContext
    private static boolean skipContext(
            AbstractChannelHandlerContext ctx, EventExecutor currentExecutor, int mask, int onlyMask) {
        // Ensure we correctly handle MASK_EXCEPTION_CAUGHT which is not included in the MASK_EXCEPTION_CAUGHT
  			//表示当前ctx是否不包含指定的操作权限
        return (ctx.executionMask & (onlyMask | mask)) == 0 ||
                																		// 当前ctx不包含mask的操作权限
                (ctx.executor() == currentExecutor && (ctx.executionMask & mask) == 0);
    }

skipContext用来判断当前AbstractChannelHandlerContext的执行mask(executionMask),是否不包含在mask或onlyMask的操作权限中。

TAG2 invokeChannelRead
AbstractChannelHandlerContext

//调用AbstractChannelHandlerContext的invokeChannelRead方法
static void invokeChannelRead(final AbstractChannelHandlerContext next, Object msg) {
  	//msg对象检查
    final Object m = next.pipeline.touch(ObjectUtil.checkNotNull(msg, "msg"), next);
  	//获取AbstractChannelHandlerContext上的executor
    EventExecutor executor = next.executor();
  	//如果executor是eventloop所绑定线程
    if (executor.inEventLoop()) {
//TAG2.1 AbstractChannelHandlerContext.invokeChannelRead
        next.invokeChannelRead(m);
    } else {
      	//调用context绑定的executor,execute执行
        executor.execute(new Runnable() {
            @Override
            public void run() {
                next.invokeChannelRead(m);
            }
        });
    }
}
TAG2.1 AbstractChannelHandlerContext.invokeChannelRead
AbstractChannelHandlerContext

    private void invokeChannelRead(Object msg) {
//TAG2.1.1 invokeHandler
  //检测当前ChannelHandler.handlerAdded(channelHandlerContext)是否执行过,如果为true,则调用实际处理事件channelRead
        if (invokeHandler()) {
            try {
//TAG2.1.2 handler().channelRead
                ((ChannelInboundHandler) handler()).channelRead(this, msg);
            } catch (Throwable t) {
                invokeExceptionCaught(t);
            }
        } 
  //如果返回false,表示当前ChannelHandler.handlerAdded(channelHandlerContext)没有被执行,需要传递事件,fireChannelRead
  else {
//TAG2.1.3 fireChannelRead
            fireChannelRead(msg);
        }
    }
TAG2.1.1 invokeHandler()---检查handler是否被add过
   AbstractChannelHandlerContext

		private boolean invokeHandler() {
        // Store in local variable to reduce volatile reads.
     		//存储当前handler的状态(是否已经被添加add过)
        int handlerState = this.handlerState;
        return handlerState == ADD_COMPLETE || (!ordered && handlerState == ADD_PENDING);
    }

这个方法,用来检测ChannelHandler.handlerAdded(channelHandlerContext)是否已经被调用,没有调用返回false,表示不调用channelHandler,只是转发事件。因为channelPipeline可能已经将channelHandler放入列表,但是没有调用add操作。

TAG2.1.2 handler().channelRead---handler方法调用

当channel读取read到信息,执行channelHandler的实际读取操作。

final class DefaultChannelHandlerContext extends AbstractChannelHandlerContext {
		//返回当前context内的ChannelHandler
    public ChannelHandler handler() {
        return handler;
    }
  
  ChannelInboundHandler
    //当当前channel已经read到信息,调用实际的handler处理器,channelRead处理
     void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception;
TAG2.1.3 fireChannelRead
AbstractChannelHandlerContext
//TAG0.0 fireChannelRead
    @Override
    public ChannelHandlerContext fireChannelRead(final Object msg) {
        invokeChannelRead(findContextInbound(MASK_CHANNEL_READ), msg);
        return this;
    }

这里重新执行TAG0.0 fireChannelRead。

流程总结:
image-20221129171215854

pipeline中消息的传递和处理流程如上。

posted @ 2023-03-10 17:23  LeasonXue  阅读(160)  评论(0)    收藏  举报