欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

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

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

前文傳送門:Netty客戶端接入流程NioSocketChannel創(chuàng)建

我們回到最初的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 {
                //創(chuàng)建jdk底層的channel
                //readBuf用于臨時承載讀到鏈接
                int localRead = doReadMessages(readBuf);
                if (localRead == 0) {
                    break;
                }
                if (localRead < 0) {
                    closed = true;
                    break;
                }
                //分配器將讀到的鏈接進行計數(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進行傳遞
            //最終會調用ServerBootstrap的內部類ServerBootstrapAcceptor的channelRead()方法
            pipeline.fireChannelRead(readBuf.get(i));
        }
        readBuf.clear();
        allocHandle.readComplete();
        pipeline.fireChannelReadComplete();
        //代碼省略
    } finally {
        //代碼省略
    }
}

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

有關pipeline的知識, 我們下一章會詳細剖析, 并會根據(jù)剖析后的內容回顧之前的有關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);
    }
}

其中參數(shù)的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(), 根據(jù)我們之前的剖析, 是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中執(zhí)行

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

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

private void register0(ChannelPromise promise) {
    try {
        //省略代碼
        //做實際的注冊
        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) {
        //省略代碼
    }
}

這段代碼我們同樣并不陌生, 因為NioServerSokectChannel中也走這一部分, 我們繼續(xù)關注doRegister()方法:

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

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

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

至此, NioSocketChannel完成注冊

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

相關文章

  • 解析如何用兩個棧來實現(xiàn)隊列的方法

    解析如何用兩個棧來實現(xiàn)隊列的方法

    本篇文章是對如何用兩個棧實現(xiàn)隊列的方法進行了詳細的分析介紹,需要的朋友參考下
    2013-06-06
  • SpringBoot中事半功倍的工具類合集分享

    SpringBoot中事半功倍的工具類合集分享

    在日常開發(fā)中經常有這樣那樣的小功能需要實現(xiàn),這些一般會作為工具類存在,在項目中有一些通用的功能,Spring內置了需要工具類,而且經過了大量的驗證,可以在開發(fā)中助你一臂之力,快跟隨小編一起來看看吧
    2023-02-02
  • Java之如何正確地對包裝類進行裝箱與拆箱

    Java之如何正確地對包裝類進行裝箱與拆箱

    在這篇文章中給大家繼續(xù)講解包裝類的裝箱和拆箱問題。你可能會很好奇,做java開發(fā),怎么還裝起箱子來了?那么就請大家?guī)е苫笸驴窗?/div> 2023-04-04
  • Java并發(fā)編程之Semaphore詳解

    Java并發(fā)編程之Semaphore詳解

    這篇文章主要介紹了Java并發(fā)編程之concurrent包中的Semaphore詳解,信號量Semaphore一般用來表示可用資源的個數(shù),相當于一個計數(shù)器,可類比生活中停車場牌子上面顯示的停車場剩余車位數(shù)量,需要的朋友可以參考下
    2023-12-12
  • Spring編程式和聲明式事務實例講解小結

    Spring編程式和聲明式事務實例講解小結

    這篇文章主要介紹了Spring編程式和聲明式事務實例講解小結,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2019-07-07
  • 詳解SpringBoot 應用如何提高服務吞吐量

    詳解SpringBoot 應用如何提高服務吞吐量

    這篇文章主要介紹了Spring Boot 應用如何提高服務吞吐量,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-07-07
  • SpringBoot @Validated注解實現(xiàn)參數(shù)分組校驗的方法實例

    SpringBoot @Validated注解實現(xiàn)參數(shù)分組校驗的方法實例

    這篇文章主要給大家介紹了關于SpringBoot @Validated注解實現(xiàn)參數(shù)分組校驗的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-09-09
  • Java使用正則表達式提取XML節(jié)點內容的方法示例

    Java使用正則表達式提取XML節(jié)點內容的方法示例

    這篇文章主要介紹了Java使用正則表達式提取XML節(jié)點內容的方法,結合具體實例形式分析了java針對xml格式字符串的正則匹配相關操作技巧,需要的朋友可以參考下
    2017-08-08
  • 用Set類判斷Map里key是否存在的示例代碼

    用Set類判斷Map里key是否存在的示例代碼

    本篇文章主要是對用Set類判斷Map里key是否存在的示例代碼進行了介紹,需要的朋友可以過來參考下,希望對大家有所幫助
    2013-12-12
  • 扒一扒 Java 中的枚舉類型

    扒一扒 Java 中的枚舉類型

    這篇文章主要給大家介紹了Java中枚舉類型的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2018-12-12

最新評論