最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

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

 更新時(shí)間:2022年03月28日 08:54:30   作者:向南是個(gè)萬人迷  
這篇文章主要為大家介紹了Netty分布式源碼分析NioSocketChannel注冊到selector方法的解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

前文傳送門:Netty客戶端接入流程N(yùn)ioSocketChannel創(chuàng)建

我們回到最初的NioMessageUnsafe的read()方法:

public void read() {
    //必須是NioEventLoop方法調(diào)用的, 不能通過外部線程調(diào)用
    assert eventLoop().inEventLoop();
    //服務(wù)端channel的config
    final ChannelConfig config = config();
    //服務(wù)端channel的pipeline
    final ChannelPipeline pipeline = pipeline();
    //處理服務(wù)端接入的速率
    final RecvByteBufAllocator.Handle allocHandle = unsafe().recvBufAllocHandle();
    //設(shè)置配置
    allocHandle.reset(config);
    boolean closed = false;
    Throwable exception = null;
    try {
        try {
            do {
                //創(chuàng)建jdk底層的channel
                //readBuf用于臨時(shí)承載讀到鏈接
                int localRead = doReadMessages(readBuf);
                if (localRead == 0) {
                    break;
                }
                if (localRead < 0) {
                    closed = true;
                    break;
                }
                //分配器將讀到的鏈接進(jìn)行計(jì)數(shù)
                allocHandle.incMessagesRead(localRead);
                //連接數(shù)是否超過最大值
            } while (allocHandle.continueReading());
        } catch (Throwable t) {
            exception = t;
        }
        int size = readBuf.size();
        //遍歷每一條客戶端連接
        for (int i = 0; i < size; i ++) {
            readPending = false;
            //傳遞事件, 將創(chuàng)建NioSokectChannel進(jìn)行傳遞
            //最終會調(diào)用ServerBootstrap的內(nèi)部類ServerBootstrapAcceptor的channelRead()方法
            pipeline.fireChannelRead(readBuf.get(i));
        }
        readBuf.clear();
        allocHandle.readComplete();
        pipeline.fireChannelReadComplete();
        //代碼省略
    } finally {
        //代碼省略
    }
}

在while循環(huán)結(jié)束之后, 將會通過一個(gè)for循環(huán)遍歷readBuf集合, 并將創(chuàng)建的NioSocketChannel傳入fireChannelRead()中, 傳播channel的讀取事件

有關(guān)pipeline的知識, 我們下一章會詳細(xì)剖析, 并會根據(jù)剖析后的內(nèi)容回顧之前的有關(guān)pipeline的操作, 這里我們只需知道, 通過fireChannelRead()我們最終調(diào)用了ServerBootstrap的內(nèi)部類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);
    }
}

其中參數(shù)的msg就是最初傳入fireChannelRead()方法的NioSocketChannel

所以這里可以通過 final Channel child = (Channel) msg 這種方式拿到NioSocketChannel

其中childGroup是我們最初初始化的work線程, 這里的register()方法跟boss線程一樣, 通過next()方法獲選擇一個(gè)線程進(jìn)行注冊, 這里不再贅述

我們緊跟調(diào)用鏈, 跟到SingleThreadEventLoop的register()方法:

public ChannelFuture register(final ChannelPromise promise) {
    ObjectUtil.checkNotNull(promise, "promise");
    promise.channel().unsafe().register(this, promise);
    return promise;
}

這里的unsafe(), 根據(jù)我們之前的剖析, 是NioByteUnsafe, 這里的register最終會調(diào)用AbstractUnsafe的register()方法, 并NioSocketChannel

不知道同學(xué)們是否記得, 當(dāng)初NioServerSocketChannel注冊的時(shí)候也走的這個(gè)方法

我們跟到register()這個(gè)方法中:

public final void register(EventLoop eventLoop, final ChannelPromise promise) {
    //省略驗(yàn)證代碼
    //所有的復(fù)制操作, 都交給eventLoop處理
    AbstractChannel.this.eventLoop = eventLoop;

    if (eventLoop.inEventLoop()) {
        //做實(shí)際主注冊
        register0(promise);
    } else {
        try {
            eventLoop.execute(new Runnable() {
                @Override
                public void run() {
                    register0(promise);
                }
            });
        } catch (Throwable t) {
            //代碼省略
        }
    }
}

我們學(xué)習(xí)過NioEventLoop相關(guān)知識之后, 應(yīng)該對這部分代碼不太陌生, 首先判斷是不是當(dāng)前NioEventLoop線程, 如果是, 則直接進(jìn)行注冊操作, 如果不是, 則封裝成task在當(dāng)前NioEventLoop中執(zhí)行

走到這里不難明白, 這里并不是當(dāng)前NioEventLoop線程, 這是boss線程執(zhí)行的, 所以這里會走到else, 如果是第一次的連接操作, work線程的NioEventLoop并沒有啟動, 所以這里也會啟動NioEventLoop, 并開始輪詢操作

跟到register0(promise)中看其是如何做實(shí)際操作的:

private void register0(ChannelPromise promise) {
    try {
        //省略代碼
        //做實(shí)際的注冊
        doRegister();
        neverRegistered = false;
        registered = true;
        //觸發(fā)事件
        pipeline.invokeHandlerAddedIfNeeded();
        safeSetSuccess(promise);
        //觸發(fā)注冊成功事件
        pipeline.fireChannelRegistered();
        if (isActive()) {
            if (firstRegistration) {
                //傳播active事件(4)
                pipeline.fireChannelActive();
            } else if (config().isAutoRead()) {
                beginRead();
            }
        }
    } catch (Throwable t) {
        //省略代碼
    }
}

這段代碼我們同樣并不陌生, 因?yàn)镹ioServerSokectChannel中也走這一部分, 我們繼續(xù)關(guān)注doRegister()方法:

protected void doRegister() throws Exception {
    boolean selected = false;
    for (;;) {
        try {
            //jdk底層的注冊方法
            //第一個(gè)參數(shù)為selector, 第二個(gè)參數(shù)表示不關(guān)心任何事件
            selectionKey = javaChannel().register(eventLoop().selector, 0, this);
            return;
        } catch (CancelledKeyException e) {
            //省略代碼
        }
    }
}

這部分也是我們之前剖析過的jdk底層的注冊, 只是不同的是, 這里的javaChannel()是SocketChanel而不是ServerSocketChannel

同樣, 這里也是表示不關(guān)心任何事件, 只是在當(dāng)前NioEventLoop綁定的selector上注冊

至此, NioSocketChannel完成注冊

以上就是Netty代碼跟蹤NioSocketChannel注冊到selector的詳細(xì)內(nèi)容,更多關(guān)于NioSocketChannel注冊到selector的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • JAVA數(shù)據(jù)結(jié)構(gòu)之漢諾塔代碼實(shí)例

    JAVA數(shù)據(jù)結(jié)構(gòu)之漢諾塔代碼實(shí)例

    這篇文章主要介紹了JAVA數(shù)據(jù)結(jié)構(gòu)之漢諾塔,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-04-04
  • Java跨域問題的幾種后端解決方式舉例詳解

    Java跨域問題的幾種后端解決方式舉例詳解

    跨域,是指瀏覽器不能執(zhí)行其他網(wǎng)站的腳本,它是由瀏覽器的同源策略造成的,是瀏覽器對JavaScript實(shí)施的安全限制,這篇文章主要給大家介紹了關(guān)于Java跨域問題的幾種后端解決方式的相關(guān)資料,需要的朋友可以參考下
    2023-11-11
  • 在Spring?MVC中使用@ControllerAdvice創(chuàng)建全局異常處理器的方法

    在Spring?MVC中使用@ControllerAdvice創(chuàng)建全局異常處理器的方法

    在Spring?MVC中,可以使用@ControllerAdvice或@RestControllerAdvice注解來定義全局異常處理器類,并使用?@ExceptionHandler注解來定義處理特定異常的方法,本文就給大家介紹了Spring?MVC?@ControllerAdvice創(chuàng)建處理器的方法,需要的朋友可以參考下
    2023-08-08
  • SpringBoot @PostMapping接收HTTP請求的流數(shù)據(jù)問題

    SpringBoot @PostMapping接收HTTP請求的流數(shù)據(jù)問題

    這篇文章主要介紹了SpringBoot @PostMapping接收HTTP請求的流數(shù)據(jù)問題,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-02-02
  • Spring Cloud Stream分區(qū)分組原理圖解

    Spring Cloud Stream分區(qū)分組原理圖解

    這篇文章主要介紹了Spring Cloud Stream的分區(qū)和分組,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-03-03
  • Mapper層繼承BaseMapper<T>需要引入的pom依賴方式

    Mapper層繼承BaseMapper<T>需要引入的pom依賴方式

    這篇文章主要介紹了Mapper層繼承BaseMapper<T>需要引入的pom依賴方式,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-01-01
  • 關(guān)于Prometheus + Spring Boot 應(yīng)用監(jiān)控的問題

    關(guān)于Prometheus + Spring Boot 應(yīng)用監(jiān)控的問題

    這篇文章主要介紹了關(guān)于Prometheus + Spring Boot 應(yīng)用監(jiān)控的問題,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-03-03
  • 利用Java寫一個(gè)學(xué)生管理系統(tǒng)

    利用Java寫一個(gè)學(xué)生管理系統(tǒng)

    今天這篇文章就給給大家分享利用Java寫一個(gè)學(xué)生管理系統(tǒng)吧,先寫一個(gè)簡單的用List來實(shí)現(xiàn)學(xué)生管理系統(tǒng):
    2021-09-09
  • Maven之分析剔除無用的jar引用問題

    Maven之分析剔除無用的jar引用問題

    這篇文章主要介紹了Maven之分析剔除無用的jar引用問題,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-09-09
  • Java技能點(diǎn)之SimpleDateFormat進(jìn)行日期格式化問題

    Java技能點(diǎn)之SimpleDateFormat進(jìn)行日期格式化問題

    這篇文章主要介紹了Java技能點(diǎn)之SimpleDateFormat進(jìn)行日期格式化問題,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-04-04

最新評論

静宁县| 仁怀市| 文水县| 翁源县| 封丘县| 巴南区| 博爱县| 木兰县| 正宁县| 黄骅市| 崇左市| 嘉兴市| 临江市| 中超| 吉首市| 时尚| 赤城县| 遂昌县| 来凤县| 南雄市| 沁源县| 满洲里市| 玉门市| 仪征市| 辽宁省| 临清市| 钟山县| 衡水市| 桂阳县| 广安市| 马尔康县| 高密市| 康马县| 乌拉特中旗| 永春县| 施秉县| 秦安县| 桦南县| 泰顺县| 德化县| 新乡市|