跳到主要内容

Netty中pipeline分析_1

概述

  • pipeline, 顾名思义, 就是管道的意思, 事件在pipeline中传输, 用户可以中断事件, 添加自己的事件处理逻辑, 可以直接将事件中断不再往下传输, 同样可以改变管道的流向, 传递其他事件。
  • 事件通常分为两种, 一是inBound入站事件, 另一种是outBound出站事件。
    • inBound事件, 顾名思义, 就是从另一端流向自己的事件, 比如读事件, 连接完成事件等等。
    • outBound, 是从自己流向另一端的事件, 比如连接事件, 写事件, 刷新缓冲区事件等等。
  • 事件是通过handler对象进行处理的, 里面封装着事件的处理逻辑.而每个handler, 是由HandlerContext进行包装的, 里面封装了对事件传输的操作。
  • 每一个channel绑定一个pipeline, 那么pipelinehandler又是什么关系?
    • pipeline可以理解成是一个双向链表, 只是存放的并不是数据而是HandlerContext, 而HandlerContext又包装了handler, 事件传输时, 从头结点(或者尾节点)开始, 找到下一个HandlerContext, 执行Handler的业务逻辑, 然后再继续往下走, 直到执行到尾节点(或者头结点, 反向)为止。

继承关系

  • 如果属于ChannelInboundHandler的子类, 则属于Inbound类型的handler
  • 如果属于ChannelOutboundHandler的子类, 则属于Outbound类型的handler

pipeline的创建

回到AbstractChannel的构造方法

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

newChannelPipeline()

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

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中代表头结点和尾节点

new TailContext(this)

尾结点的构建

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
    • executor为null
    • TAIL_NAME是当前handler, 也就是自身的命名
    • true代表自身是inboundHandler
    • fasle代表自身不是outboundHandler

AbstractChannelHandlerContext的构造方法

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

new HeadContext(this)

头结点的构建

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;
}
}
  1. 看过了tail节点, head节点就不难理解, 同样继承了AbstractChannelHandlerContext, 说明自身是一个HandlerContext, 与tail不同的是, 这里实现了ChannelOutboundHandler接口和ChannelOutboundHandler接口, 说明其既能处理inbound事件也能处理outbound的事件, handler方法返归自身, 说明自身是一个handler
  2. 在构造方法中初始化了一个Unsafe类型的成员变量, 是通过自身绑定的channel拿到的, 说明这个类中可以进行对channel的读写操作。这里同样调用了父类的构造方法, 不同的是, 这里inbound参数传入了false, 而outbound参数传入了true, 这里说明这里标志的事件是outbound事件。同学们可能疑惑, 为什么同时执行ChannelOutboundHandler接口和ChannelOutboundHandler接口,但是标志的事件不同?
  3. 其实这两个地方应用的场景是不同的, 继承ChannelOutboundHandlerChannelOutboundHandler, 说明其既能处理inbound事件也能处理outBound的事件, 但是只有outbound属性为true说明自身是一个outboundhandler, 是一个可以处理inbound事件的outboundhandler(估计被绕晕了), 这两种handler主要是保证在事件传输中保证事件的单方向流动, 在后面事件传输我们能领会到。

AbstractChannelHandlerContext的构造方法

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;
}

AbstractChannelHandlerContext的构建和尾结点构建时相同

回到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;
}

介绍完了new TailContext(this)new HeadContext(this),继续分析

head.next = tail;
tail.prev = head;

tail节点和head节点中的nextprev属性, 其实是其父类AbstractChannelHandlerContext, 每一个handlerContext都拥有这两个属性, 代表自身的下一个节点和上一个节点, 因为我们概述中介绍过pipeline其实是一个双向链表, 所以其中每一个节点必须有指向其他节点的指针。