当前位置:首页 > 谈天说地

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

34资源网2022-03-28487

我们回到最初的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的资料请关注萬仟网其它相关文章!

看完文章,还可以扫描下面的二维码下载快手极速版领4元红包

快手极速版二维码

快手极速版新人见面礼

除了扫码领红包之外,大家还可以在快手极速版做签到,看视频,做任务,参与抽奖,邀请好友赚钱)。

邀请两个好友奖最高196元,如下图所示:

快手极速版邀请好友奖励

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

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

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

分享给朋友:

相关文章

一千元如何创业?一千元创业项目有吗?

一千元如何创业?一千元创业项目有吗?

一千元如何创业?有的人想用一千元创业,说实话,现实当中一千元根本创不了业,你买器材都不够,更别提创业了。当然,如果你在网络上面,那还是有可能创业的。因为现在网上有很多可以投资1000元左右创业的项目。下面,小编就给大家分享三个这样的创业项目…

谈2022年平衡发展策略,我们要平衡的发展

谈2022年平衡发展策略,我们要平衡的发展

2022年解决方案的第二个关键词叫平衡。我们要平衡的发展,长期的发展。你的个人生活,你的公司事业,还有国家的形势,我觉得一定要平衡的去发展,不能说我只赚钱,身体就搞垮,或者说我只赚快钱,但是不关心国家的形势。你看,密室逃脱这个行业,上周国家…

第二家东南亚美股上市公司诞生,Grab为何上市即大跌?

第二家东南亚美股上市公司诞生,Grab为何上市即大跌?

编者按:本文来自微信公众号美股研究社(ID:meigushe),创业邦经授权转载 在很长一段时间内,来自新加坡、发家于东南亚市场的Sea(冬海集团)都被外界称为造富神话。并非因为其“东南亚小腾讯”的影子,而是其强大的游戏和电商业务支撑它制霸…

如何删掉分页符空白页(空白页的解决方法)

如何删掉分页符空白页(空白页的解决方法)

我相信大家在编辑Word文档时,一定都遇到过这种恼人的情况,好不容易编辑完文档了,却发现末尾留下了空白页,想删除都无从下手。那么到底如何快速删除Word空白页呢?今天就来教大家几招,保证让你删得干干净净! 方法一:Shift键删除空白页…

最便宜的智能机手机(最新手机排行榜2021 )

最便宜的智能机手机(最新手机排行榜2021 )

这个双11的手机市场,各家确实都是全力以赴了,因为一方面下半年就是这个重要节点,另一方面市场需求也不是很高,更需要加速出货。这不,评价君看到,iQOO Neo5活力版也发力了,原价2299元的机型,到手价最低1899元,十分彪悍。 这款i…

适合小孩用的手机(教你一个简单的办法)

适合小孩用的手机(教你一个简单的办法)

1/12 11月15日,IPRO科技正式发布了全球首款自律智能旗舰IPRO学生手机P100,这台手机解决了家长们对“孩子玩手机”这件事的担忧,也打破了市场对学生手机的刻板印象。 2/12 3/12 IPRO 学生手机 P100 打破了传…