Pipeline Handler Context 三者的关系

1.每当ServerSocket创建一个新的连接,就会创建一个Socket,对应的就是目标客户端
2.每一个新创建的Socket 都将会分配一个全新的 ChannelPipeline (简称pipeline)
3.每一个ChannelPipeline 内部含有多个ChannelHandlerontext(简称Context)
4.他们一起组成了双向链表,这些Context用于包装我们调用addLast方法时添加的ChannelHandler(简称Handler)
image.png
上图中:
1.ChannelSocket 和 ChannelPipeline 是一对一的关联关系,而pipeline内部的多个 Context形成了链表,Context 只是对 Handler的封装
2.当一个请求进来的时候,会进入Socket对应的pipeline,并经过pipeline所有的handler,就是设计模式中的过滤器模式


Pipeline Handler Context 创建过程

分为三个步骤:
1.任何一个ChannelSocket创建同时都会创建一个pipeline
2.当用户或系统内部调用pipeline的addList(或addFirst等)方法时,都会创建一个包装这个handler的context
3.这些Context在pipeline中组成了双向链表


1) pipeline 添加 handler,参数是线程池,name 是 null, handler 是我们或者系统传入的 handler。Netty 为了防止多个线程导致安全问题,同步了这段代码,步骤如下:
2) 检查这个 handler 实例是否是共享的,如果不是,并且已经被别的 pipeline 使用了,则抛出异常。
3) 调用 newContext(group, filterName(name, handler), handler) 方法,创建一个 Context。从这里可以看出来了,每次添加一个 handler 都会创建一个关联 Context。
4) 调用 addLast 方法,将 Context 追加到链表中。
5) 如果这个通道还没有注册到 selecor 上,就将这个 Context 添加到这个 pipeline 的待办任务中。当注册好了以后,就会调用 callHandlerAdded0 方法(默认是什么都不做,用户可以实现这个方法)。
6) 到这里,针对三对象创建过程,了解的差不多了,和最初说的一样,每当创建 ChannelSocket 的时候都会创建一个绑定的 pipeline,一对一的关系,创建 pipeline 的时候也会创建 tail 节点和 head 节点,形成最初的链表。tail是入站 inbound 类型的 handler, head 既是 inbound 也是 outbound 类型的 handler。在调用 pipeline 的 addLast方法的时候,会根据给定的 handler 创建一个 Context,然后,将这个 Context 插入到链表的尾端(tail 前面)。到此就 OK 了


Pipeline Handler HandlerContext 创建过程梳理

1.每当创建ChannelSocket的时候都会创建一个绑定的pipeline,一对一的关系,创建pipeline的时候也会创建tail节点和head节点,形成最初的链表
2.在调用pipeline的addLast方法的时候,会根据给定的handler创建一个Context,然后将这个Context插入到链表的尾端
3.Context包装handler,多个Context在pipeline中形成双向链表
4.入站方向叫inbound,由head节点开始,出站方向叫outbound,由tail节点开始


ChannelPipeline 调度 handler 的源码剖析

1.首先,当一个请求进来的时候,会第一个调用pipeline的相关方法,如果是入站事件,这些方法由fire开头,表示开始管道的流动,让后面的handler继续处理


说明:
出站是 tail 开始,入站从 head 开始。因为出站是从内部向外面写,从 tail 开始,能够让前面的handler 进行处理,防止 handler 被遗漏,比如编码。反之,入站当然是从 head 往内部输入,让后面的 handler 能够处理这些输入的数据。比如解码。因此虽然 head 也实现了 outbound 接口,但不是从 head 开始执行出站任务


关于如何调度

image.png
说明:
1.piprline首先会调用Context的静态方法 fireXXX,并传入Context
2.然后,静态方法调用Context的invoker方法,而invoker方法内部会调用该Context所包含的Handler的真正的XXX方法,调用结束后,如果还需要继续向后传递,就调用Context的fireXXX2方法,循环直到调用完所有的handler


ChannelPipeline调度handler梳理

1.Context包装handler,多个Context在pipeline中形成了双向链表,入站方向叫inbound,从head节点开始,出站方向叫outbound,从tail节点开始
2.而节点中间传递通过AbstractChannelHandlerContext类内部的fire系列方法,找到当前节点的下一个节点不断的循环传播。是一个过滤器形式完成对handler的调度