<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          剖析Netty之底層原理(三)

          共 760字,需瀏覽 2分鐘

           ·

          2020-12-17 12:27

          神秘北極圈 阿拉斯加的山巔

          誰(shuí)的臉出現(xiàn)海角的天邊

          忽然的瞬間在那遙遠(yuǎn)的地點(diǎn)

          我看見(jiàn)戀人幸福的光點(diǎn)

          靈魂在招喚唱著古老

          陌生熟悉的歌謠 天空 在微笑

          我的世界繽紛閃耀





          前面渾渾噩噩的把服務(wù)端的實(shí)現(xiàn)底層源碼來(lái)了個(gè)大致,感覺(jué)頭有點(diǎn)大,這里用圖例的方式來(lái)理下思緒。


          一、EventLoopGroup bossGroup = new NioEventLoopGroup();

          這是服務(wù)端的第一句代碼,類(lèi)似的還new了一個(gè)workGroup,工作線程組

          這兩句代碼,Netty底層的各種初始化動(dòng)作,前面也都說(shuō)過(guò)了,這里做個(gè)總結(jié):


          底層逐步初始化調(diào)用程序如下圖:


          5adb79a4b71e73b5ea37d50fb4a8bdfc.webp



          其類(lèi)調(diào)用時(shí)序圖如下所示


          f14e3a4c00879c9780e0e0cdf471e0ff.webp


          這里,需要重點(diǎn)看下

          io.netty.util.concurrent.MultithreadEventExecutorGroup#MultithreadEventExecutorGroup

          (int,?

          java.util.concurrent.Executor,

          io.netty.util.concurrent.EventExecutorChooserFactory, java.lang.Object...

          )方法

          源碼如下:


          protected MultithreadEventExecutorGroup(int nThreads, Executor executor,                                            EventExecutorChooserFactory chooserFactory, Object... args) {????????????????//當(dāng)線程數(shù)沒(méi)有的時(shí)候,拋出異常,根據(jù)前面分析,這里的線程數(shù)為服務(wù)器內(nèi)核數(shù)量*2        if (nThreads <= 0) {            throw new IllegalArgumentException(String.format("nThreads: %d (expected: > 0)", nThreads));        }
          ????????//這里的Executor是null,所以初始化一個(gè) if (executor == null) { //初始化一個(gè)類(lèi)型是io.netty.util.concurrent.ThreadPerTaskExecutor的線程池 //線程池類(lèi)型為io.netty.util.concurrent.DefaultThreadFactory executor = new ThreadPerTaskExecutor(newDefaultThreadFactory()); }
          // 設(shè)置事件驅(qū)動(dòng)數(shù)組,大小根據(jù)設(shè)定或者默認(rèn)的來(lái) children = new EventExecutor[nThreads];
          for (int i = 0; i < nThreads; i ++) { boolean success = false; try {????????????????//設(shè)定每個(gè)事件驅(qū)動(dòng)數(shù)組為io.netty.channel.nio.NioEventLoop????????????????//這里調(diào)用的newChild,下面會(huì)有詳細(xì)解釋 children[i] = newChild(executor, args); success = true; } catch (Exception e) { // TODO: Think about if this is a good exception type throw new IllegalStateException("failed to create a child event loop", e); } finally { if (!success) { for (int j = 0; j < i; j ++) { //如果添加失敗,則關(guān)閉每一個(gè)io.netty.channel.nio.NioEventLoop children[j].shutdownGracefully(); }
          for (int j = 0; j < i; j ++) { EventExecutor e = children[j]; try { while (!e.isTerminated()) { e.awaitTermination(Integer.MAX_VALUE, TimeUnit.SECONDS); } } catch (InterruptedException interrupted) { // Let the caller handle the interruption. Thread.currentThread().interrupt(); break; } } } } }
          ????????//初始化io.netty.util.concurrent.EventExecutorChooserFactory.EventExecutorChooser????????//其結(jié)果值為io.netty.util.concurrent.DefaultEventExecutorChooserFactory.PowerOfTwoEventExecutorChooser#PowerOfTwoEventExecutorChooser????????//或者io.netty.util.concurrent.DefaultEventExecutorChooserFactory.GenericEventExecutorChooser#GenericEventExecutorChooser chooser = chooserFactory.newChooser(children);
          final FutureListener terminationListener = new FutureListener() { @Override public void operationComplete(Future future) throws Exception { if (terminatedChildren.incrementAndGet() == children.length) { terminationFuture.setSuccess(null); } } };
          for (EventExecutor e: children) {????????????//?循環(huán)為每一個(gè)事件驅(qū)動(dòng)器實(shí)例添加監(jiān)聽(tīng)????????????//這里的e.terminationFuture()實(shí)質(zhì)調(diào)用????????????//io.netty.util.concurrent.SingleThreadEventExecutor#terminationFuture????????????//因?yàn)榍懊嫖覀冋f(shuō)到每一個(gè)children數(shù)組的實(shí)例是io.netty.channel.nio.NioEventLoop????????????//這里io.netty.channel.nio.NioEventLoop繼承自????????????//io.netty.util.concurrent.SingleThreadEventExecutor#terminationFuture e.terminationFuture().addListener(terminationListener); }
          ????????//這里將children復(fù)制出來(lái)一份給到readonlyChildren ????????//Collections.unmodifiableSet返回的Set集合不可修改,即readonly Set childrenSet = new LinkedHashSet(children.length); Collections.addAll(childrenSet, children); readonlyChildren = Collections.unmodifiableSet(childrenSet); }


          如上所示為netty-all-4.1.50.final源碼,其大致意義,在上面代碼中也有添加注釋?zhuān)偨Y(jié)一下就是這里設(shè)定了事件驅(qū)動(dòng)數(shù)組,并設(shè)定事件輪詢線程組


          上面的給每一個(gè)EventExecutor數(shù)組賦值的代碼

          這里可以發(fā)現(xiàn)

          io.netty.util.concurrent.MultithreadEventExecutorGroup

          類(lèi)中,該方法是靜態(tài)方法


          750a0ae623b7eabd1e890be9d64a0858.webp


          方法是由子類(lèi)

          io.netty.channel.nio.NioEventLoopGroup

          調(diào)用而來(lái),所以這里實(shí)質(zhì)調(diào)用的是

          io.netty.channel.nio.NioEventLoopGroup#newChild


          源碼如下:

          @Override    protected EventLoop newChild(Executor executor, Object... args) throws Exception {        EventLoopTaskQueueFactory queueFactory = args.length == 4 ? (EventLoopTaskQueueFactory) args[3] : null;        return new NioEventLoop(this, executor, (SelectorProvider) args[0],            ((SelectStrategyFactory) args[1]).newSelectStrategy(), (RejectedExecutionHandler) args[2], queueFactory);    }


          這里的args數(shù)組,在根據(jù)以上配置的情況下,是3,第一個(gè)是選擇器:

          args[0]?=?SelectorProvider.provider()

          即:


          843437ff57c4878655b29482d43cdf2a.webp


          數(shù)組第二個(gè)元素是默認(rèn)選擇器策略

          args[1]?=?DefaultSelectStrategyFactory.INSTANCE;

          即:


          aaaa9849c2232458ffc71ef51e6f11b8.webp


          第三個(gè)是默認(rèn)異常

          args[2]?=?RejectedExecutionHandlers.reject();


          661bc9d13b1cf1fbfbc583570cb8642a.webp


          下面主要看下

          io.netty.channel.nio.NioEventLoopGroup#newChild

          方法


          該方法上面源代碼已說(shuō)明,返回了一個(gè)

          io.netty.channel.nio.NioEventLoop#NioEventLoop

          對(duì)象


          be551028ed9268c21dfecd51db69fc4c.webp


          構(gòu)造方法調(diào)用明細(xì)如下所示:


          901297d656bd65f957e4b81ac2d9da1f.webp


          io.netty.channel.nio.NioEventLoop?

          的構(gòu)造方法,通過(guò)逐層super,為父級(jí)類(lèi)參數(shù)賦值,同時(shí)創(chuàng)建了

          NioEventLoop的多路復(fù)用選擇器


          d277c7029df2ccce008c83b9a483e599.webp


          這里可以看下Netty的多路復(fù)用選擇器是如何構(gòu)建的:

          源碼如下:


          private SelectorTuple openSelector() {        final Selector unwrappedSelector;        try {????????????//首先直接打開(kāi)選擇器            unwrappedSelector = provider.openSelector();        } catch (IOException e) {            throw new ChannelException("failed to open a new selector", e);        }
          if (DISABLE_KEY_SET_OPTIMIZATION) {????????????//這里選擇是否不需要優(yōu)化多路復(fù)用選擇器的key????????????//默認(rèn)是false,即默認(rèn)需要優(yōu)化????????????//可以通過(guò)properties文件中io.netty.noKeySetOptimization設(shè)定true或者false return new SelectorTuple(unwrappedSelector); }
          ????????//AccessController?是Java安全策略機(jī)制的一種方式,這里表示的是,????????//不管是否設(shè)定安全策略,這里臨時(shí)擴(kuò)大訪問(wèn)權(quán)限,強(qiáng)制執(zhí)行方法??????????????//有需要了解更詳細(xì)的,可以自行查閱資料 Object maybeSelectorImplClass = AccessController.doPrivileged(new PrivilegedAction() { @Override public Object run() { try {????????????????????//嘗試返回sun.nio.ch.SelectorImpl實(shí)例,可能會(huì)拋出異常 return Class.forName( "sun.nio.ch.SelectorImpl", false, PlatformDependent.getSystemClassLoader()); } catch (Throwable cause) { return cause; } } });
          if (!(maybeSelectorImplClass instanceof Class) || // ensure the current selector implementation is what we can instrument. !((Class) maybeSelectorImplClass).isAssignableFrom(unwrappedSelector.getClass())) {????????????if?(maybeSelectorImplClass?instanceof?Throwable)?{ Throwable t = (Throwable) maybeSelectorImplClass; logger.trace("failed to instrument a special java.util.Set into: {}", unwrappedSelector, t); } //當(dāng)嘗試獲取的sun.nio.ch.SelectorImpl實(shí)例是異常時(shí)候,則直接返回 return new SelectorTuple(unwrappedSelector); }
          final Class selectorImplClass = (Class) maybeSelectorImplClass; final SelectedSelectionKeySet selectedKeySet = new SelectedSelectionKeySet();
          Object maybeException = AccessController.doPrivileged(new PrivilegedAction() { @Override public Object run() { try { //這里利用反射,獲取到selectedKeys和publicSelectedKeys Field selectedKeysField = selectorImplClass.getDeclaredField("selectedKeys"); Field publicSelectedKeysField = selectorImplClass.getDeclaredField("publicSelectedKeys");????????????????????//當(dāng)java版本在9或者以上,并且sun.misc.Unsafe可以在classpath下找到????????????????????//這里如果java版本在1.9及其以上,一般來(lái)說(shuō),都是可以的 if (PlatformDependent.javaVersion() >= 9 && PlatformDependent.hasUnsafe()) { // Let us try to use sun.misc.Unsafe to replace the SelectionKeySet. // This allows us to also do this in Java9+ without any extra flags.????????????????????????//這里原始注釋也比較好理解了:嘗試用sun.misc.Unsafe替換SelectionKeySet long selectedKeysFieldOffset = PlatformDependent.objectFieldOffset(selectedKeysField); long publicSelectedKeysFieldOffset = PlatformDependent.objectFieldOffset(publicSelectedKeysField);
          if (selectedKeysFieldOffset != -1 && publicSelectedKeysFieldOffset != -1) { PlatformDependent.putObject( unwrappedSelector, selectedKeysFieldOffset, selectedKeySet); PlatformDependent.putObject( unwrappedSelector, publicSelectedKeysFieldOffset, selectedKeySet); return null; } // We could not retrieve the offset, lets try reflection as last-resort. }
          Throwable cause = ReflectionUtil.trySetAccessible(selectedKeysField, true); if (cause != null) { return cause; } cause = ReflectionUtil.trySetAccessible(publicSelectedKeysField, true); if (cause != null) { return cause; }????????????????????//給屬性設(shè)置值 selectedKeysField.set(unwrappedSelector, selectedKeySet); publicSelectedKeysField.set(unwrappedSelector, selectedKeySet); return null; } catch (NoSuchFieldException e) { return e; } catch (IllegalAccessException e) { return e; } } });
          if (maybeException instanceof Exception) { selectedKeys = null; Exception e = (Exception) maybeException; logger.trace("failed to instrument a special java.util.Set into: {}", unwrappedSelector, e); return new SelectorTuple(unwrappedSelector); } selectedKeys = selectedKeySet; logger.trace("instrumented a special java.util.Set into: {}", unwrappedSelector); return new SelectorTuple(unwrappedSelector, new SelectedSelectionKeySetSelector(unwrappedSelector, selectedKeySet)); }


          上面代碼,需要注意的地方:


          各種賦值,打開(kāi)的多路復(fù)用器


          d8c05dc987504212189dcc053e49e05a.webp


          賦值到了

          io.netty.channel.nio.NioEventLoop.SelectorTuple

          屬性中


          同時(shí)這個(gè)多路復(fù)用器的父級(jí)類(lèi)

          sun.nio.ch.SelectorImpl

          屬性被做出了優(yōu)化,

          即針對(duì)多路復(fù)用選擇器實(shí)現(xiàn)類(lèi)

          sun.nio.ch.SelectorImpl

          進(jìn)行了優(yōu)化

          這里為何需要做這種優(yōu)化呢?


          首先需要知道,原本的sun.nio.ch.SelectorImpl

          結(jié)構(gòu)是什么樣子的?


          41c7efa515a33b9ff075da26d5da0249.webp


          如上圖所示,原本的

          sun.nio.ch.SelectorImpl#selectedKeys

          sun.nio.ch.SelectorImpl#publicSelectedKeys

          屬性是一個(gè)HashSet,而HashSet底層其實(shí)也就是一個(gè)HashMap,所以,其數(shù)據(jù)結(jié)構(gòu)主要是由鏈表組成,鏈表就是一個(gè)不連續(xù)的內(nèi)存存儲(chǔ),方便插入和刪除,但是不利于查詢

          所以這里替換了一個(gè)

          io.netty.channel.nio.SelectedSelectionKeySet

          其構(gòu)造方法為:


          de5bfcc5e1b0a1dd4e181a14651928bf.webp


          即是一個(gè)數(shù)組,我們知道數(shù)組在內(nèi)存是一個(gè)連續(xù)的過(guò)程,有一個(gè)連續(xù)的內(nèi)存地址,數(shù)組不利于新增和刪除,但是利于查詢



          而這里

          sun.nio.ch.SelectorImpl#selectedKeys

          sun.nio.ch.SelectorImpl#publicSelectedKeys

          主要存儲(chǔ)的是和事件感興趣的key值,即前面NIO中說(shuō)到的可連接、可讀、可寫(xiě)等狀態(tài):


          eb4bf2610edb2f1d0d7f3ef317cc691a.webp


          所以這里主要是在輪詢的時(shí)候方便獲取這種狀態(tài)值,即快速查詢,所以這里用數(shù)組替換鏈表


          最終返回了一個(gè)優(yōu)化后的

          io.netty.channel.nio.NioEventLoop.SelectorTuple


          這里的

          io.netty.channel.nio.NioEventLoop.SelectorTuple

          也是較之前NIO中所得到的

          java.nio.channels.Selector

          多路復(fù)用器不同,看下它的結(jié)構(gòu):


          fda2054afb40bc2505ee1ace322e3e32.webp


          io.netty.channel.nio.NioEventLoop.SelectorTuple

          io.netty.channel.nio.NioEventLoop的一個(gè)內(nèi)部類(lèi),包含2個(gè)多路復(fù)用器,根據(jù)構(gòu)造函數(shù),這里返回的

          io.netty.channel.nio.NioEventLoop.SelectorTuple

          屬性值分別是:


          io.netty.channel.nio.NioEventLoop.SelectorTuple#unwrappedSelector

          值為

          java.nio.channels.Selector


          io.netty.channel.nio.NioEventLoop.SelectorTuple#selector

          值為

          io.netty.channel.nio.SelectedSelectionKeySetSelector#SelectedSelectionKeySetSelector


          為此,在經(jīng)歷這一系列的關(guān)聯(lián)調(diào)用之后(具體源碼邏輯請(qǐng)見(jiàn)《剖析Netty之底層原理(一)》),其主要源碼類(lèi)的主要參數(shù)變化,這里總結(jié)了一張圖表,


          9760d7db49141e35c1377947e0faef14.webp

          其中上圖中,具有相似顏色的類(lèi),是同一個(gè)類(lèi),


          針對(duì)此,可以初步了解完

          EventLoopGroup bossGroup = new NioEventLoopGroup();

          EventLoopGroup workerGroup = new NioEventLoopGroup();

          方法所執(zhí)行的所有邏輯<兩者邏輯一樣>


          這里簡(jiǎn)單做出一個(gè)小結(jié):


          初始化NioEventLoopGroup的結(jié)果,實(shí)質(zhì)是構(gòu)建了一個(gè)EventExecutor數(shù)組,其數(shù)組類(lèi)型是NioEventLoop。


          由于篇幅已經(jīng)夠長(zhǎng)了,所以,后續(xù)將接著分享,這里先簡(jiǎn)單告一段落。


          有喜歡的,歡迎點(diǎn)贊關(guān)注,謝謝



          麻煩給個(gè)再看呢!

          瀏覽 50
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                    <th id="afajh"><progress id="afajh"></progress></th>
                    青青草视频免费在线 | 五月色综合网 | 青春草视频免费在线观看 | 黄色一级片在线播放 | 成年女人黄色电影 |