Netty源码分析第4章(pipeline)---->第1节: pipeline的建立

 

Netty源码分析第四章: pipelinehtml

 

概述:数据结构

         pipeline, 顾名思义, 就是管道的意思, netty, 事件在pipeline中传输, 用户能够中断事件, 添加本身的事件处理逻辑, 能够直接将事件中断再也不往下传输, 一样能够改变管道的流向, 传递其余事件.这里有点相似于SpringAOP, 可是比AOP实现起来简单的多ide

        事件一般分为两种, 一是inBound事件, 另外一种是outBound事件, inBound事件, 顾名思义, 就是从另外一端流向本身的事件, 好比读事件, 链接完成事件等等, outBound, 是从本身流向另外一端的事件, 好比链接事件, 写事件, 刷新缓冲区事件等等源码分析

        netty, 事件是经过handler对象进行处理的, 里面封装着事件的处理逻辑.而每一个handler, 是由HandlerContext进行包装的, 里面封装了对事件传输的操做学习

        经过以前的学习, 咱们知道每个channel绑定一个pipeline, 那么pipelinehandler又是什么关系呢?this

        其实pipeline咱们能够理解成是一个双向链表的数据结构, 只是其中存放的并非数据而是HandlerContext, HandlerContext又包装了handler, 事件传输过程当中, 从头结点(或者尾节点)开始, 找到下一个HandlerContext, 执行其Handler的业务逻辑, 而后再继续往下走, 直到执行到尾节点(或者头结点, 反向)为止, 经过一幅图了解其大概逻辑:spa

4-0-1线程

        这里head表明pipeline的头结点, tail表明pipeline的尾节点, 这两个节点是会随着pipeline的初始化而建立, 而且不会被删除3d

        HandlerContext的简单继承关系比较简单, 默认的是DefaultChannelHandlerContext, 继承于AbstractChannelHandlerContext 指针

        而Handler分为InboundHandleroutBoundHandler, Inbound专门处理inbound事件, outBound专门用于处理outBound事件

 

        继承关系以下图:

4-0-2

        从图中不难看出, 若是属于ChannelInboundHandler的子类, 则属于Inbound类型的handler

        若是是ChannelOutboundHandler的子类, 则属于Outbound类型的handler

 

        了解了其大概逻辑, 咱们继续跟到源码中, 看其实如何体现的:

 

第一节: pipeline的建立

回顾以前NioServerSocketChannel的建立过程

咱们看AbstractChannel的构造方法:

protected AbstractChannel(Channel parent) { this.parent = parent; id = newId(); unsafe = newUnsafe(); pipeline = newChannelPipeline(); }

 

咱们跟到newChannelPipeline():

protected DefaultChannelPipeline newChannelPipeline() { //传入当前channel
    return new DefaultChannelPipeline(this); }

 

咱们看到这里建立了一个DefaultChannelPipeline, 并将自身channel传入

继续跟DefaultChannelPipeline的构造方法:

protected DefaultChannelPipeline(Channel channel) { this.channel = ObjectUtil.checkNotNull(channel, "channel"); succeededFuture = new SucceededChannelFuture(channel, null); voidPromise =  new VoidChannelPromise(channel, true); tail = new TailContext(this); head = new HeadContext(this); head.next = tail; tail.prev = head; }

 

首先保存了当前channel

而后保存了两个属性succeededFuture, voidPromise, 这两个属性是Future相关的内容, 以后的章节会讲到

首先, 这里初始化了两个节点, head节点和tail节点, pipeline中表明头结点和尾节点

 

咱们首先跟到这tail节点类中,也就是TailContext类:

final class TailContext extends AbstractChannelHandlerContext implements ChannelInboundHandler { TailContext(DefaultChannelPipeline pipeline) { //inbound处理器
        super(pipeline, null, TAIL_NAME, true, false); //将当前节点设置为已添加, head和tail.....
 setAddComplete(); } //自身也是handler
 @Override public ChannelHandler handler() { return this; } //方法省略

这个是DefualtPipline的内部类, 首先看其继承了AbstractChannelHandlerContext, 说明自身是个HandlerContext, 同时也实现ChannelInboundHander接口, 而且其中的handler()方法返回了自身, 说明自身也是handler, 而实现ChannelInboundHander, 说明自身只处理Inbound事件

 

构造方法中, 调用了父类的构造器, 看其中参数:

pipeline是自身所属的pipeline

executornull

TAIL_NAME是当前handler, 也就是自身的命名

true表明自身是inboundHandler

fasle表明自身不是outboundHandler

 

继续跟到父类构造方法中:

AbstractChannelHandlerContext(DefaultChannelPipeline pipeline, EventExecutor executor, String name, boolean inbound, boolean outbound) { //名字
    this.name = ObjectUtil.checkNotNull(name, "name"); //pipeline
    this.pipeline = pipeline; //线程处理器
    this.executor = executor; //事件标识
    this.inbound = inbound; this.outbound = outbound; ordered = executor == null || executor instanceof OrderedEventExecutor; }

这里初始化了自身父类的几个属性

pipeline为自身绑定的pipeline

exeutor是线程执行器, 这里为空

inboundoutbound是事件标志, 这里分别是truefalse, 也就是自身属于inboundHnadler而不属于outboundHandler

 

回到DefaultChannelPipeline的构造方法:

protected DefaultChannelPipeline(Channel channel) { this.channel = ObjectUtil.checkNotNull(channel, "channel"); succeededFuture = new SucceededChannelFuture(channel, null); voidPromise =  new VoidChannelPromise(channel, true); tail = new TailContext(this); head = new HeadContext(this); head.next = tail; tail.prev = head; }

再看HeadContext:

final class HeadContext extends AbstractChannelHandlerContext implements ChannelOutboundHandler, ChannelInboundHandler { private final Unsafe unsafe; HeadContext(DefaultChannelPipeline pipeline) { super(pipeline, null, HEAD_NAME, false, true); unsafe = pipeline.channel().unsafe(); setAddComplete(); } @Override public ChannelHandler handler() { return this; } }

看过了tail节点, head节点就不难理解, 一样继承了AbstractChannelHandlerContext, 说明自身是一个HandlerContext, tail不一样的是, 这里实现了ChannelOutboundHandler接口和ChannelOutboundHandler接口, 说明其既能处理inbound事件也能处理outbound的事件, handler方法返归自身, 说明自身是一个handler

 

在构造方法中初始化了一个Unsafe类型的成员变量, 是经过自身绑定的channel拿到的, 说明这个类中能够进行对channel的读写操做

这里一样调用了父类的构造方法, 不一样的是, 这里inbound参数传入了false, outbound参数传入了true, 这里说明这里标志的事件是outbound事件

同窗们可能疑惑, 为何同时执行ChannelOutboundHandler接口和ChannelOutboundHandler可是标志的事件不一样?

 

其实这两个地方应用的场景是不一样的, 继承ChannelOutboundHandlerChannelOutboundHandler, 说明其既能处理inbound事件也能处理outBound的事件, 可是只有outbound属性为true说明自身是一个outboundhandler, 是一个能够处理inbound事件的outboundhandler(估计被绕晕了), 这两种handler主要是保证在事件传输中保证事件的单方向流动, 在后面事件传输咱们能领会到

 

 

再跟进父类的构造方法, 又是咱们熟悉的部分:

AbstractChannelHandlerContext(DefaultChannelPipeline pipeline, EventExecutor executor, String name, boolean inbound, boolean outbound) { //名字
    this.name = ObjectUtil.checkNotNull(name, "name"); //pipeline
    this.pipeline = pipeline; //线程处理器
    this.executor = executor; //事件标识
    this.inbound = inbound; this.outbound = outbound; ordered = executor == null || executor instanceof OrderedEventExecutor; }

初始化了pipeline, executor, 和事件标识的属性

 

 

回到DefaultChannelPipeline的构造方法:

protected DefaultChannelPipeline(Channel channel) { this.channel = ObjectUtil.checkNotNull(channel, "channel"); succeededFuture = new SucceededChannelFuture(channel, null); voidPromise =  new VoidChannelPromise(channel, true); tail = new TailContext(this); head = new HeadContext(this); head.next = tail; tail.prev = head; }

咱们介绍完了head, tail这两个context, 继续往下看:

head.next = tail;

tail.prev = head;

 

tail节点和head节点中的nextprev属性, 实际上是其父类AbstractChannelHandlerContext, 每个handlerContext都拥有这两个属性, 表明自身的下一个节点和上一个节点, 由于咱们概述中介绍过pipeline实际上是一个双向链表, 因此其中每个节点必须有指向其余节点的指针, 熟悉双向连接数据结构的同窗应该不会陌生

 

 

这里head节点的next属性是tail节点, tail节点的prev属性是head, 说明当前双向链表只有两个节点, headtail, 其中head下一个节点指向tail, tail的上一个节点指向head, 如图所示:

4-1-1

以上就是pipeline的初始化过程

 

上一节: 监听读事件

下一节: handler的添加

相关文章
相关标签/搜索