netty原始碼學習之channelHander的組織管理
阿新 • • 發佈:2022-05-12
當netty server啟動時 呼叫bind方式 時 會開始註冊serverChannel
有必要說下 pipeline.addLast 方法
它在新增一個hander的時候 會把 把這個hander包裝成 context 然後填加在 pipeline 的headContext 後面 如果沒有註冊時 會
if (!registered) {
newCtx.setAddPending();
//新增一個初始化邏輯 新增到 pipeline 裡面 在對應channel 註冊時 pipeline 會呼叫到它 (下面有分析)
callHandlerCallbackLater(newCtx, true);
return this;
}
那麼 上面那段程式碼 他是非同步的 它是什麼時候 呼叫的呢 ?
在呼叫 register方法 時 最終會走到
io.netty.channel.AbstractChannel.AbstractUnsafe#register0 裡面
劃線那一步 就會調到
上面說的那一步 一步邏輯裡面 具體的邏輯 請看後面分析
ServerBootstrapAcceptor有什麼用呢 它繼承了 ChannelInboundHandlerAdapter 所以 當客戶端 連線伺服器時 會進入的它的read方法
下面來看 它的read方法
child.pipeline().addLast(childHandler); 這行很重要
childHandler 其實就是我們自己傳的 初始化hander 一般形式 都是 下面紅線這一塊
那麼 child 是什麼呢 其實很好理解 他就是 serverSocketChannel.accept 的到的那個 socketChannel
現在 伺服器 在accept 之後 把 這個 socketChannel 註冊 到 workGroup中的一個 eventLoop 裡面 現在 進入 register方法裡面
invokeHandlerAddedIfNeeded() 只會呼叫一次 在具體瞭解 這個方法的邏輯之前 我們有必要知道 pipieline的 addLast 方法的邏輯
@Override
public final ChannelPipeline addLast(EventExecutorGroup group, String name, ChannelHandler handler) {
final AbstractChannelHandlerContext newCtx;
synchronized (this) {
checkMultiplicity(handler);
//生成一個新的 context
newCtx = newContext(group, filterName(name, handler), handler);
//將這個context新增到head後面 head ->newContext->tail
addLast0(newCtx);
//這裡很重要 pipeline 還沒有註冊 那麼 生成一個回撥 它引用了我們剛剛生成的context 它將會在後續用到
// If the registered is false it means that the channel was not registered on an eventLoop yet.
// In this case we add the context to the pipeline and add a task that will call
// ChannelHandler.handlerAdded(...) once the channel is registered.
if (!registered) {
newCtx.setAddPending();
callHandlerCallbackLater(newCtx, true);
return this;
}
EventExecutor executor = newCtx.executor();
if (!executor.inEventLoop()) {
callHandlerAddedInEventLoop(newCtx, executor);
return this;
}
}
callHandlerAdded0(newCtx);
return this;
}
現在進入
private void callHandlerAddedForAllHandlers() {
final PendingHandlerCallback pendingHandlerCallbackHead;
synchronized (this) {
assert !registered;
// This Channel itself was registered.
registered = true;
//這個就是我們剛剛 新增的那個回撥 PendingHanderCallBack
pendingHandlerCallbackHead = this.pendingHandlerCallbackHead;
// Null out so it can be GC'ed.
this.pendingHandlerCallbackHead = null;
}
// This must happen outside of the synchronized(...) block as otherwise handlerAdded(...) may be called while
// holding the lock and so produce a deadlock if handlerAdded(...) will try to add another handler from outside
// the EventLoop.
PendingHandlerCallback task = pendingHandlerCallbackHead;
while (task != null) {
//開始執行
task.execute();
task = task.next;
}
}
task.execute 其實 邏輯就是 開始執行 我們的hander的 handerAdd方法 因為我們初始化hander繼承了
io.netty.channel.ChannelInitializer
所以 下面看下它的邏輯
好 現在我們serverChannel.accept 得到的那個 channel 它的pipeline 已經 設定完畢了 繼續流程
ok 我們的accept 的 chanel註冊完畢 且對應的pipeline 也這是完畢了 也出發了 對應的channel的 生命週期方法