什么是Netty事件传播

发布时间:2021-06-23 14:10:39 作者:chen
来源:亿速云 阅读:402

本篇内容主要讲解“什么是Netty事件传播”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“什么是Netty事件传播”吧!

Netty高性能的背后,蕴含着优秀的设计。 今天我们从源码角度详细介绍Netty中ChannelPipeline的事件,以及这些事件是如何在ChannelPipeline中传播的。

ChannelPipeline

ChannelPipeline是负责管理ChannelHandler的有序容器。 其内部维护着一个由ChannelHandlerContext做为节点的双向链表。 Netty上的事件便是通过这个链表进行传播的。

一图胜千言

什么是Netty事件传播

ChannelPipeline需要注意以下几个关键点:

其中, 入站事件包括:

出站事件包括:

handler里可以触发任意的事件,即在InboundHandler里可以触发出站事件,而OutboundHandler里也可以触发入站事件。但注意不要出现事件的死循环。

更进一步的,我们从源码上去解读ChannelPipeline的几个要点:

    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(DefaultChannelPipeline pipeline) {
        super(pipeline, null, HEAD_NAME, true, true);   // outbound=true
        unsafe = pipeline.channel().unsafe();   // 出站事件传播到了头节点后,便调用该unsafe对象上的方法
        setAddComplete();
    }

    TailContext(DefaultChannelPipeline pipeline) {
        super(pipeline, null, TAIL_NAME, true, false);  // inboud=true
        setAddComplete();
    }

    protected void onUnhandledInboundMessage(Object msg) {
        try {
            logger.debug(
                    "Discarded inbound message {} that reached at the tail of the pipeline. " +
                            "Please check your pipeline configuration.", msg);
        } finally {
            ReferenceCountUtil.release(msg);    // 释放引用,当引用为0时,便可回收内存空间
        }
    }

    protected void onUnhandledInboundChannelReadComplete() {    // 空处理
    }

    @Override
    public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
        unsafe.write(msg, promise);     // 通过unsafe将数据输出
    }
    @Override
    public final ChannelPipeline fireChannelActive() {
        AbstractChannelHandlerContext.invokeChannelActive(head); //触发head节点入站事件
        return this;
    }

    @Override
    public final ChannelFuture writeAndFlush(Object msg) {
        return tail.writeAndFlush(msg); // 触发tail节点出站事件
    }
private AbstractChannelHandlerContext newContext(EventExecutorGroup group, String name, ChannelHandler handler) {
        return new DefaultChannelHandlerContext(this, childExecutor(group), name, handler); // 实例化含handler的ChannelHandlerContext对象
    }

    private void addFirst0(AbstractChannelHandlerContext newCtx) {
        AbstractChannelHandlerContext nextCtx = head.next;
        newCtx.prev = head;
        newCtx.next = nextCtx;
        head.next = newCtx;     // 新节点插入头结点后面
        nextCtx.prev = newCtx;
    }

    private void addLast0(AbstractChannelHandlerContext newCtx) {
        AbstractChannelHandlerContext prev = tail.prev;
        newCtx.prev = prev;
        newCtx.next = tail;
        prev.next = newCtx;
        tail.prev = newCtx;     // 新节点插入尾节点前面
    }

ChannelHandlerContext

ChannelHandlerContext是ChannelPipeline双向链表中的节点。 它是连接ChannelHandler和ChannelPipeline的桥梁。有了它ChannelHandler才有机会响应并处理ChannelPipeline中的事件。

其源码不复杂,其中ChannelHandlerContext的findContextInbound/findContextOutbound 是实现入站事件传递给InboundHandler出站事件传递给OutboundHandler的关键。 其实现也比较简单,就是判断context的后续(入站事件)/前驱(出站事件)节点对应的handler实现是否是inbound/outbound,如果不是则遍历下一个节点,直至尾节点/头节点。

而在上面的分析中,我们已经知道尾节点实例化时,inbound被设置为ture,头节点实例化时,outbound被设置为ture。 这便形成的遍历的终止条件。

    private AbstractChannelHandlerContext findContextInbound() {
        AbstractChannelHandlerContext ctx = this;
        do {
            ctx = ctx.next;
        } while (!ctx.inbound); //直到尾节点,因为尾节点inbound在Pipeline中被定义为Ture
        return ctx;
    }

    private AbstractChannelHandlerContext findContextOutbound() {
        AbstractChannelHandlerContext ctx = this;
        do {
            ctx = ctx.prev;
        } while (!ctx.outbound);//直到头节点,因为头节点outbound在Pipeline中被定义为Ture
        return ctx;
    }

正是由于Netty这些优秀的设计,才使得其高性能下,仍然被灵活使用。 因此也被大家所接受并深爱着。


到此,相信大家对“什么是Netty事件传播”有了更深的了解,不妨来实际操作一番吧!这里是亿速云网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

推荐阅读:
  1. Netty事件监听和处理(下)
  2. Netty事件监听和处理(上)

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

netty

上一篇:linux 中ss命令如何使用

下一篇:QuaZIP介绍、编译和使用

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》