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

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

34资源网2022-03-28419

我们回到最初的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

分享给朋友:

相关文章

适合白手起家的十个创业点子,好好看下吧

适合白手起家的十个创业点子,好好看下吧

创业对于很多人来说,不仅仅意味着去实现自己的梦想,还能让自己走上不一样的人生。在这里我给大家分享一些创业的点子,希望能帮助到大家!…

带货直播运营怎么做(直播公司盈利模式)

带货直播运营怎么做(直播公司盈利模式)

直播网红千千万,谁能争当NO.1?随着直播崛起,越来越多的人想要入场分一杯羹,BUT,80%的人都不懂直播运营的内容法则。那么,新手主播怎么玩才能快速脱颖而出呢?掌握这四大直播运营的内容规则,人气轻松翻倍!1. 直播内容多样化…

抖音上热门技巧有哪些(dou+投粉丝量还是点赞量)

抖音上热门技巧有哪些(dou+投粉丝量还是点赞量)

前不久,“越来和锅锅”发布了自己的第一条抖音视频,结果该视频一天的播放量达到了2581万,至今获赞205.7万。可见,选择适合自己的视频表现方式比努力更重要。 (图片来源:抖音APP) 抖音如何上热门,一直是小伙伴们想要了解的答案。 如果…

裁员,爱奇艺穿越生死线

裁员,爱奇艺穿越生死线

图源:摄图网 编者按:本文来自微信公众号霞光社(ID:Globalinsights)),作者:麻吉、郭照川、韩夏,创业邦经授权转载 霞光社从多位爱奇艺员工处了解到,本轮裁员罕见覆盖了爱奇艺所有部门,从影业、IP、游戏、电商部门,甚至到经纪公…

扫地机器人市场的2021:后浪翻涌,前浪头疼

扫地机器人市场的2021:后浪翻涌,前浪头疼

编者按:本文来自锋见,创业邦经授权发布。 转眼2021年已接近尾声,2022年即将来临。回顾过去这一年,注定是不平凡的一年,特别是对于扫地机器人行业来说,2021年发生了不少大事,对行业影响深远。今天我们就来盘点和点评一下。 科技改变生活,…