当前位置:首页 > 谈天说地 > 正文内容

Netty分布式NioSocketChannel注册到selector方法解析

34资源网2022年03月28日 13:09298

我们回到最初的niomessageunsafe的read()方法:

public void read() {
    //必须是nioeventloop方法调用的, 不能通过外部线程调用
    assert eventloop().ineventloop();
    //服务端channel的config
    final channelconfig config = config();
    //服务端channel的pipeline
    final channelpipeline pipeline = pipeline();
    //处理服务端接入的速率
    final recvbytebufallocator.handle allochandle = unsafe().recvbufallochandle();
    //设置配置
    allochandle.reset(config);
    boolean closed = false;
    throwable exception = null;
    try {
        try {
            do {
                //创建jdk底层的channel
                //readbuf用于临时承载读到链接
                int localread = doreadmessages(readbuf);
                if (localread == 0) {
                    break;
                }
                if (localread < 0) {
                    closed = true;
                    break;
                }
                //分配器将读到的链接进行计数
                allochandle.incmessagesread(localread);
                //连接数是否超过最大值
            } while (allochandle.continuereading());
        } catch (throwable t) {
            exception = t;
        }
        int size = readbuf.size();
        //遍历每一条客户端连接
        for (int i = 0; i < size; i ++) {
            readpending = false;
            //传递事件, 将创建niosokectchannel进行传递
            //最终会调用serverbootstrap的内部类serverbootstrapacceptor的channelread()方法
            pipeline.firechannelread(readbuf.get(i));
        }
        readbuf.clear();
        allochandle.readcomplete();
        pipeline.firechannelreadcomplete();
        //代码省略
    } finally {
        //代码省略
    }
}

在while循环结束之后, 将会通过一个for循环遍历readbuf集合, 并将创建的niosocketchannel传入firechannelread()中, 传播channel的读取事件

有关pipeline的知识, 我们下一章会详细剖析, 并会根据剖析后的内容回顾之前的有关pipeline的操作, 这里我们只需知道, 通过firechannelread()我们最终调用了serverbootstrap的内部类serverbootstrapacceptor 中的channelread()方法

跟到channelread()方法中:

public void channelread(channelhandlercontext ctx, object msg) {
    final channel child = (channel) msg;
    //代码省略
    try {
        //work线程注册channel
        childgroup.register(child).addlistener(new channelfuturelistener() {
            @override
            public void operationcomplete(channelfuture future) throws exception {
                if (!future.issuccess()) {
                    forceclose(child, future.cause());
                }
            }
        });
    } catch (throwable t) {
        forceclose(child, t);
    }
}

其中参数的msg就是最初传入firechannelread()方法的niosocketchannel

所以这里可以通过 final channel child = (channel) msg 这种方式拿到niosocketchannel

其中childgroup是我们最初初始化的work线程, 这里的register()方法跟boss线程一样, 通过next()方法获选择一个线程进行注册, 这里不再赘述

我们紧跟调用链, 跟到singlethreadeventloop的register()方法:

public channelfuture register(final channelpromise promise) {
    objectutil.checknotnull(promise, "promise");
    promise.channel().unsafe().register(this, promise);
    return promise;
}

这里的unsafe(), 根据我们之前的剖析, 是niobyteunsafe, 这里的register最终会调用abstractunsafe的register()方法, 并niosocketchannel

不知道同学们是否记得, 当初nioserversocketchannel注册的时候也走的这个方法

我们跟到register()这个方法中:

public final void register(eventloop eventloop, final channelpromise promise) {
    //省略验证代码
    //所有的复制操作, 都交给eventloop处理
    abstractchannel.this.eventloop = eventloop;

    if (eventloop.ineventloop()) {
        //做实际主注册
        register0(promise);
    } else {
        try {
            eventloop.execute(new runnable() {
                @override
                public void run() {
                    register0(promise);
                }
            });
        } catch (throwable t) {
            //代码省略
        }
    }
}

我们学习过nioeventloop相关知识之后, 应该对这部分代码不太陌生, 首先判断是不是当前nioeventloop线程, 如果是, 则直接进行注册操作, 如果不是, 则封装成task在当前nioeventloop中执行

走到这里不难明白, 这里并不是当前nioeventloop线程, 这是boss线程执行的, 所以这里会走到else, 如果是第一次的连接操作, work线程的nioeventloop并没有启动, 所以这里也会启动nioeventloop, 并开始轮询操作

跟到register0(promise)中看其是如何做实际操作的:

private void register0(channelpromise promise) {
    try {
        //省略代码
        //做实际的注册
        doregister();
        neverregistered = false;
        registered = true;
        //触发事件
        pipeline.invokehandleraddedifneeded();
        safesetsuccess(promise);
        //触发注册成功事件
        pipeline.firechannelregistered();
        if (isactive()) {
            if (firstregistration) {
                //传播active事件(4)
                pipeline.firechannelactive();
            } else if (config().isautoread()) {
                beginread();
            }
        }
    } catch (throwable t) {
        //省略代码
    }
}

这段代码我们同样并不陌生, 因为nioserversokectchannel中也走这一部分, 我们继续关注doregister()方法:

protected void doregister() throws exception {
    boolean selected = false;
    for (;;) {
        try {
            //jdk底层的注册方法
            //第一个参数为selector, 第二个参数表示不关心任何事件
            selectionkey = javachannel().register(eventloop().selector, 0, this);
            return;
        } catch (cancelledkeyexception e) {
            //省略代码
        }
    }
}

这部分也是我们之前剖析过的jdk底层的注册, 只是不同的是, 这里的javachannel()是socketchanel而不是serversocketchannel

同样, 这里也是表示不关心任何事件, 只是在当前nioeventloop绑定的selector上注册

至此, niosocketchannel完成注册

以上就是netty代码跟踪niosocketchannel注册到selector的详细内容,更多关于niosocketchannel注册到selector的资料请关注萬仟网其它相关文章!

看完文章,还可以用支付宝扫描下面的二维码领取一个支付宝红包,目前可领1-88元不等

支付宝红包二维码

除了扫码可以领取之外,大家还可以(复制 720087999 打开✔支付宝✔去搜索, h`o`n.g.包哪里来,动动手指就能领)。

看下图所示是好多参与这次活动领取红包的朋友:

支付宝红包

扫描二维码推送至手机访问。

版权声明:本文由34楼发布,如需转载请注明出处。

本文链接:https://www.34l.com/post/11176.html

分享给朋友:

相关文章

适合普通人做的小本创业点子
适合普通人做的小本创业点子

适合普通人做的小本创业生意有什么??随着零售行业的兴起,小型超市便利店生意成为创业者首选的项目之一,主要原因在于:投入资金小、回笼快,不需要太大的现金流来支撑、一年半左右就能回本。这对于拥有一部分闲置资金,想创业的投资者来说简直是很好的创业...

分享30句用被刺造句的句子
分享30句用被刺造句的句子

1、黄昏已经谢去,夜幕早已铺开。高高的法国梧桐,被刺眼的白色路灯照亮。在黑色的夜空里镶了一圈又一圈攫绿,有时被拂过的夜风飘动,发出轻轻的沙沙声,只那么一阵,就消失在无限的宁静之中。2、一个人的羞耻心在基本一点上被刺痛,那么,它的余波会在不知...

引流文案微信推广(微商引流推广文案模板)
引流文案微信推广(微商引流推广文案模板)

大家好啊!今天又跟大家分享小技巧啦~往下看↓↓↓ 首先说一下什么样的文案是引流型的?实际上,一句话是将公共域流量定向到您的私有域流量池。其目的是先引流然后慢慢进行信任激活变现。 在标题方面,通常有以下几种类型,今天为大家详细描述一下。...

应用汇下载安装最新版(2021最新版应用汇app)
应用汇下载安装最新版(2021最新版应用汇app)

Donews8月17日消息(记者 邱慧)近日,为安卓手机服务的应用型软件“应用汇”新版正式上线,同时推出“应用收藏”功能——“应用集”。 应用集主要分为“推荐”、“最热”、“最新”三类。应用汇官方介绍,此次新版上线后,安装包被优化缩小,...

卡斯数据是干什么的(免费大数据查询平台)
卡斯数据是干什么的(免费大数据查询平台)

短视频/直播电商不负众望,成为2020年品牌营销最热关键词。G2格局下两大顶流——抖音和快手,也自然吸引了各方关注。相较抖音而言,快手独特的老铁氛围像自带结界,不懂“规矩”的内容创作者和品牌方在这里寸步难行。 究竟快手直播电商现状如何?什...

lenovo手机网上哪里买(联想旗舰店官网商城)
lenovo手机网上哪里买(联想旗舰店官网商城)

昨晚联想拯救者电竞手机 2 Pro 正式发布,搭载骁龙 888 旗舰芯片、八指操控体系,配备 6.92 英寸 AMOLED 144Hz 三星定制电竞无孔屏幕,5500mAh 容量电池,堪称 “堆料狂魔”,这款手机于今日 10:00 正式开售...