您当前的位置: 首页 >  pip

恐龙弟旺仔

暂无认证

  • 0浏览

    0关注

    282博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

Netty源码解析-ChannelPipeline与ChannelHandler初探

恐龙弟旺仔 发布时间:2021-12-20 12:31:30 ,浏览量:0

前言:

    前文中的EventLoop分析中,我们知道了每个EventLoop都有一个对应的Selector,用于关注注册在其上的Channel的各种读写事件。

    当发生读写事件时,会交由Unsafe(本质上也是Channel的包装类)来处理,比如读事件

// 1.在NioEventLoop.run中,接收到读事件,直接调用unsafe来处理,如下2方法所示
unsafe.read();

// 2.AbstractNioByteChannel.read
@Override
public final void read() {
    final ChannelConfig config = config();
    if (shouldBreakReadReady(config)) {
        clearReadPending();
        return;
    }
    final ChannelPipeline pipeline = pipeline();
	...
    ByteBuf byteBuf = null;
    boolean close = false;
    try {
        do {
            byteBuf = allocHandle.allocate(allocator);
            allocHandle.lastBytesRead(doReadBytes(byteBuf));
            ...
            // 事件处理交由ChannelPipeline
            pipeline.fireChannelRead(byteBuf);
            byteBuf = null;
        } while (allocHandle.continueReading());

所以,要知道读事件该如何处理,理解ChannelPipeline是非常有必要的。

所以本文先来将ChannelPipeline、ChannelHandlerContext、ChannelHandler之间的关系理清楚。

1.ChannelPipeline

    依照之前的惯例,不知道这个接口是做什么的,就先看注释

/**
 * A list of {@link ChannelHandler}s which handles or intercepts inbound events and outbound operations of a
 * {@link Channel}.  {@link ChannelPipeline} implements an advanced form of the
 * Intercepting Filter pattern
 * to give a user full control over how an event is handled and how the {@link ChannelHandler}s in a pipeline
 * interact with each other.
 * 
 */
public interface ChannelPipeline
        extends ChannelInboundInvoker, ChannelOutboundInvoker, Iterable {

    
    
}

有几个重点:

ChannelPipeline是一组ChannelHandler的集合;

ChannelPipeline的实现是一种拦截过滤器模式;

用户可以自定义ChannelHandler来进行事件处理;

1.1 ChannelPipeline类结构图

 

笔者比较喜欢这种视图,干脆直接,可以较快找到接口的重要方法。

* ChannelPipeline接口主要提供的是对ChannelHandler的操作,增删(方法addLast、remove)等(毕竟之前说过ChannelPipeline是一组ChannelPipeline的集合);还有就是一系列的fire开头的方法(用于触发对各种读写注册类事件的响应),后续我们会仔细分析;

* 其父接口ChannelInboundInvoker,主要提供的是inbound(入事件,比如注册、可读事件等)的操作;

* 另一个父接口ChannelOutboundInvoker,主要提供的是outbound(出事件,比如连接远程服务、可写出事件等)的操作;

* Iterable就比较好理解了,就是用来循环获取内部类(ChannelHandler类)

1.2 ChannelPipeline默认实现与构造

    ChannelPipeline接口提供了默认实现类DefaultChannelPipeline,我们来看下其构造方法及主要属性

public class DefaultChannelPipeline implements ChannelPipeline {
    // pipeline对应的头部和尾部Handler实现
    final AbstractChannelHandlerContext head;
    final AbstractChannelHandlerContext tail;

    // pipeline所属的channel
    private final Channel channel;
    // 是否被注册
    private boolean registered;
    
    // 默认构造方法
    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;
    }
}

从ChannelPipeline的基本属性和其默认构造方法中,我们了解到,ChannelPipeline属于某一个Channel;并且其构造了一个双向链表,tail和head互相指向;

但是这个TailContext和HeadContext到底是什么呢?我们先不纠结,继续往下看。

2.ChannelHandlerContext

    上述2中的TailContext和HeadContext本质上是ChannelHandlerContext接口的实现。

/**
 * Enables a {@link ChannelHandler} to interact with its {@link ChannelPipeline}
 * and other handlers.
 **/
public interface ChannelHandlerContext extends AttributeMap, ChannelInboundInvoker, ChannelOutboundInvoker {

    
}

    从注释中我们可以看出来,ChannelHandlerContext是一个关联接口,用于关联ChannelPipeline和其他ChannelHandler。

2.1 ChannelHandlerContext类结构

 

    与ChannelPipeline类似,ChannelHandlerContext也继承了ChannelInboundInvoker和ChannelOutboundInvoker接口,这两个接口与之前分析ChannelPipeline时是一样的功能,也是用于inbound和outbound事件的处理;

    不太一样的就是ChannelHandlerContext接口本身有对channel和ChannelHandler的依赖。

    只看这些抽象的方法我们还看不出什么来,不用担心,带着疑问继续往下看。

2.2 ChannelHandlerContext默认实现与构造
// DefaultChannelHandlerContext就是ChannelHandlerContext的默认实现
final class DefaultChannelHandlerContext extends AbstractChannelHandlerContext {

    private final ChannelHandler handler;

    // 在构造方法中传入ChannelPipeline和ChannelHandler等参数
    DefaultChannelHandlerContext(
            DefaultChannelPipeline pipeline, EventExecutor executor, String name, ChannelHandler handler) {
        super(pipeline, executor, name, handler.getClass());
        this.handler = handler;
    }

    @Override
    public ChannelHandler handler() {
        return handler;
    }
}

// AbstractChannelHandlerContext构造实现
abstract class AbstractChannelHandlerContext implements ChannelHandlerContext, ResourceLeakHint {

    private static final InternalLogger logger = InternalLoggerFactory.getInstance(AbstractChannelHandlerContext.class);
    // 前一个和后一个ChannelHandlerContext节点
    volatile AbstractChannelHandlerContext next;
    volatile AbstractChannelHandlerContext prev;
    // 关联的ChannelPipeline
    private final DefaultChannelPipeline pipeline;
    
    AbstractChannelHandlerContext(DefaultChannelPipeline pipeline, EventExecutor executor,
                                  String name, Class            
关注
打赏
1655041699
查看更多评论
0.2863s