当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 方法的逻辑
@Overridepublic 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的 生命周期方法
Original: https://www.cnblogs.com/pupansheng/p/16261826.html
Author: 蒲蒲的博客
Title: netty源码学习之channelHander的组织管理
原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/569549/
转载文章受原作者版权保护。转载请注明原作者出处!