四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也具有链式调用的关键。

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

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;
}

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

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

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

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

invoker内方法,会执行相应的inbound操作,并在操作完成后,调用channel.channelPipelin上的下一个ChannelInboundHandler上对应的方法被调用,实现pipeline上handlerContext的链式调用。
inboundInvoker上的方法都是以fireXXX命名。
public interface ChannelInboundInvoker {
/**
* 注册channel到它的eventloop上
*这个方法,会使channel上的pipeline中的下一个ChannelInboundHandler的channelRegistered(ChannelHandlerContext)方法被调用
*/
ChannelInboundInvoker fireChannelRegistered();

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。
流程总结:
pipeline中消息的传递和处理流程如上。

浙公网安备 33010602011771号