- Outbound事件是请求事件。
- Outbound事件的发起者是Channel,处理者是Unsafe。
- Outbound事件在Pipeline中传输方向是tail -> head。
Outbount事件其中之一bind,以bind为例:
AbstractChannel
bind(SocketAddress localAddress, ChannelPromise promise):
@Override
public ChannelFuture bind(SocketAddress localAddress, ChannelPromise promise) {
return pipeline.bind(localAddress, promise);
}
- 该方法实现自ChannelOutboundInvoker接口。
- 方法内部调用被被bind(SocketAddress localAddress, ChannelPromise promise) 方法。
看bind(SocketAddress localAddress, ChannelPromise promise) 方法的具体实现:
@Override
public final ChannelFuture bind(SocketAddress localAddress, ChannelPromise promise) {
return tail.bind(localAddress, promise);
}
@Override
public ChannelFuture bind(final SocketAddress localAddress, final ChannelPromise promise) {
if (localAddress == null) {
throw new NullPointerException("localAddress");
}
// 判断 Promise 对象是否合法。
if (isNotValidPromise(promise, false)) {
// cancelled
return promise;
}
// 获得下一个 Outbound 节点
final AbstractChannelHandlerContext next = findContextOutbound();
// 获得下一个 Outbound 节点的执行器
EventExecutor executor = next.executor();
// 调用下一个 Outbound 节点的 bind 方法
if (executor.inEventLoop()) {
next.invokeBind(localAddress, promise);
} else {
safeExecute(executor, new Runnable() {
@Override
public void run() {
next.invokeBind(localAddress, promise);
}
}, promise, null);
}
return promise;
}
上面判断promise对象是否合法,isNotValidPromise(ChannelPromise promise, boolean allowVoidPromise)
private boolean isNotValidPromise(ChannelPromise promise, boolean allowVoidPromise) {
if (promise == null) {
throw new NullPointerException("promise");
}
// Promise 已经完成
if (promise.isDone()) {
// Check if the promise was cancelled and if so signal that the processing of the operation
// should not be performed.
//
// See https://github.com/netty/netty/issues/2349
if (promise.isCancelled()) {
return true;
}
throw new IllegalArgumentException("promise already done: " + promise);
}
// Channel 不符合
if (promise.channel() != channel()) {
throw new IllegalArgumentException(String.format(
"promise.channel does not match: %s (expected: %s)", promise.channel(), channel()));
}
// DefaultChannelPromise 合法
if (promise.getClass() == DefaultChannelPromise.class) {
return false;
}
// 禁止 VoidChannelPromise
if (!allowVoidPromise && promise instanceof VoidChannelPromise) {
throw new IllegalArgumentException(
StringUtil.simpleClassName(VoidChannelPromise.class) + " not allowed for this operation");
}
// 禁止 CloseFuture
if (promise instanceof AbstractChannel.CloseFuture) {
throw new IllegalArgumentException(
StringUtil.simpleClassName(AbstractChannel.CloseFuture.class) + " not allowed in a pipeline");
}
return false;
}
关于调用findContextOutbound()方法,获得下一个Outbound节点:
注意从pipeline的tail->head。
private AbstractChannelHandlerContext findContextOutbound() {
// 循环,向前获得一个 Outbound 节点
AbstractChannelHandlerContext ctx = this;
do {
ctx = ctx.prev;
} while (!ctx.outbound);
return ctx;
}
调用 AbstractChannelHandlerContext#executor() 方法,获得下一个Outbound节点的执行器:
如果未设置子执行器,则Channel的EventLoop作为执行器。
// Will be set to null if no child executor should be used, otherwise it will be set to the
// child executor.
// EventExecutor 对象
final EventExecutor executor;
@Override
public EventExecutor executor() {
if (executor == null) {
return channel().eventLoop();
} else {
return executor;
}
}
- 如果在EventLoop的线程中,那么调用下一个节点的invokeBind(SocketAddress localAddress, ChannelPromise promise) 方法,传播 bind 事件给下一个节点。
- 如果不在EventLoop线程中,调用safeExecute(EventExecutor executor, Runnable runnable, ChannelPromise promise, Object msg)方法,提交到EventLoop的线程中执行:
private static void safeExecute(EventExecutor executor, Runnable runnable, ChannelPromise promise, Object msg) {
try {
// 提交到 EventLoop 的线程中,进行执行任务
executor.execute(runnable);
} catch (Throwable cause) {
try {
// 发生异常,回调通知 promise 相关的异常
promise.setFailure(cause);
} finally {
// 释放 msg 相关的资源
if (msg != null) {
ReferenceCountUtil.release(msg);
}
}
}
}
invokeBind(SocketAddress localAddress, ChannelPromise promise) 方法:
private void invokeBind(SocketAddress localAddress, ChannelPromise promise) {
if (invokeHandler()) {
// 判断是否符合的 ChannelHandler
// 如果是不符合的ChannelHandler,则跳过该节点。
try {
// 调用该 ChannelHandler 的 bind 方法
((ChannelOutboundHandler) handler()).bind(this, localAddress, promise);
} catch (Throwable t) {
notifyOutboundHandlerException(t, promise); // 通知 Outbound 事件的传播,发生异常
}
} else {
// 跳过,传播 Outbound 事件给下一个节点
bind(localAddress, promise);
}
}
上面调用InvokeHandler()方法,判断是否是符合的ChannelHandler:
/**
* Makes best possible effort to detect if {@link ChannelHandler#handlerAdded(ChannelHandlerContext)} was called
* yet. If not return {@code false} and if called or could not detect return {@code true}.
*
* If this method returns {@code false} we will not invoke the {@link ChannelHandler} but just forward the event.
* This is needed as {@link DefaultChannelPipeline} may already put the {@link ChannelHandler} in the linked-list
* but not called {@link ChannelHandler#handlerAdded(ChannelHandlerContext)}.
*/
private boolean invokeHandler() {
// Store in local variable to reduce volatile reads.
int handlerState = this.handlerState;
return handlerState == ADD_COMPLETE || (!ordered && handlerState == ADD_PENDING);
}
这里。ordered = true的节点,必须与ChannelHandler已添加完毕。
ordered = false的节点,没有ChannelHandler的要求。
bind(ChannelHandlerContext ctx, SocketAddress localAddress, ChannelPromise promise) 方法:
@Override
public void bind(ChannelHandlerContext ctx, SocketAddress localAddress, ChannelPromise promise) throws Exception {
unsafe.bind(localAddress, promise);
}
unsafe进行处理。说明Unsafe是bind的处理者。
- Inbound事件是通知事件。
- Inbound事件发起者是Unsafe,处理者是TailContext。
- Inbound事件在Pipeline中传输方向是head -> tail。
Inbound和Outbound很相似,镜像。俺就不说啦。