<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之底層原理(二)

          共 1748字,需瀏覽 4分鐘

           ·

          2020-11-20 03:02

          逃離整個(gè)宇宙碰撞的意外

          穿過(guò)黑暗盡頭又通往哪里

          時(shí)間也被吞沒(méi)到了無(wú)人之際

          是否能留住和你的記憶

          星空不規(guī)則

          無(wú)盡下墜


          上次說(shuō)到調(diào)用

          io.netty.bootstrap.AbstractBootstrap#init

          方法

          由于是服務(wù)端,則實(shí)際調(diào)用

          io.netty.bootstrap.ServerBootstrap#init

          方法



          132-133行:設(shè)置通道相關(guān)屬性

          135行:從通道中獲取

          io.netty.channel.ChannelPipeline

          獲取的ChannelPipeline是獲取的啥呢?

          這里是從一個(gè)

          io.netty.channel.Channel

          中獲取的,這個(gè)Channel,是前面

          中得到的,上文說(shuō)到,這里是通過(guò)反射調(diào)用對(duì)應(yīng)類的構(gòu)造方法獲取的,而這個(gè)對(duì)應(yīng)類,是傳入的

          io.netty.channel.socket.nio.NioServerSocketChannel

          那么這里的

          io.netty.channel.Channel#pipeline


          實(shí)質(zhì)是調(diào)用上圖顯示的

          io.netty.channel.AbstractChannel#pipeline

          方法,因?yàn)?/span>

          io.netty.channel.socket.nio.NioServerSocketChannel

          是繼承于

          io.netty.channel.AbstractChannel



          這里是直接返回AbstractChannel的一個(gè)屬性值

          io.netty.channel.DefaultChannelPipeline

          那么這個(gè)屬性值是什么時(shí)候賦值的呢?

          剖析Netty之底層原理(一)中,有說(shuō)到過(guò),初始化的Channel時(shí),是通過(guò)反射調(diào)用

          io.netty.channel.socket.nio.NioServerSocketChannel

          的無(wú)參構(gòu)造,

          這里再回顧下這個(gè)無(wú)參構(gòu)造:


          執(zhí)行完

          io.netty.channel.socket.nio.NioServerSocketChannel#newSocket

          之后,得到一個(gè)

          java.nio.channels.ServerSocketChannel對(duì)象,再調(diào)用

          io.netty.channel.socket.nio.NioServerSocketChannel#NioServerSocketChannel(java.nio.channels.ServerSocketChannel)

          方法

          即:


          這里調(diào)用了父類方法,我們逐個(gè)點(diǎn)擊進(jìn)去



          如上述過(guò)程所示,這里調(diào)用了

          io.netty.channel.AbstractChannel#AbstractChannel(io.netty.channel.Channel)

          方法

          設(shè)置了屬性值

          io.netty.channel.DefaultChannelPipeline

          這里的

          newChannelPipeline

          方法,實(shí)質(zhì)調(diào)用

          io.netty.channel.AbstractChannel#newChannelPipeline

          方法,





          這里我們需要重點(diǎn)看這個(gè)類:

          io.netty.channel.AbstractChannelHandlerContext

          上圖可以發(fā)現(xiàn),設(shè)置了

          io.netty.channel.AbstractChannelHandlerContext#next


          io.netty.channel.AbstractChannelHandlerContext#prev

          這里維護(hù)的兩個(gè)

          io.netty.channel.AbstractChannelHandlerContext

          其結(jié)果構(gòu)成一個(gè)雙向鏈表

          類似這樣子的一個(gè)結(jié)果:


          關(guān)于這個(gè)設(shè)計(jì)的目的,待后續(xù)使用到的時(shí)候再進(jìn)一步了解,這里先了解到此


          接著說(shuō)上面的初始化方法

          137-138行:將類屬性值,賦予成員變量,這里需要指出的是,這里的

          EventLoopGroup是前面我們?cè)O(shè)置的工作線程組,

          ChannelHandler是前面我們?cè)O(shè)置的childHandler

          即:




          140-143行:將Map, Object>

          轉(zhuǎn)化為Entry, Object>[]數(shù)組

          這里的Map,?Object>,是在初始化ServerbootStrap中設(shè)置的

          即,設(shè)置的.option


          ?

          145-162行:主要是設(shè)置這個(gè)ChannelPipeline

          調(diào)用

          io.netty.channel.ChannelPipeline#addLast(io.netty.channel.ChannelHandler...)

          方法

          傳入

          io.netty.channel.ChannelInitializer

          對(duì)象,這里重寫了

          io.netty.channel.ChannelInitializer#initChannel(io.netty.channel.ChannelHandlerContext)

          方法,

          將自定義的Handler設(shè)置到pipeline中

          這里先不深入到Pipeline中描述如何添加自定義的Handler了,后續(xù)將有詳細(xì)的說(shuō)明


          這里我們需要重點(diǎn)看下這幾個(gè)addLast方法:截圖顯示下


          這里主要分為2個(gè)部分,一個(gè)是148行-152行,另一部分是154-160行

          148-152行:

          這里重寫了

          io.netty.channel.ChannelInitializer#initChannel

          方法,傳入的這個(gè)通道,很明顯就是前面設(shè)置的

          io.netty.channel.socket.nio.NioServerSocketChannel

          從服務(wù)端socket通道中獲取到pipeline

          149行,讀取配置的handler,前面并沒(méi)有設(shè)置,所以這里是null

          故而不會(huì)執(zhí)行if方法,結(jié)束運(yùn)行

          154-160行:

          154行,從

          io.netty.channel.socket.nio.NioServerSocketChannel

          獲取事件輪詢同時(shí)執(zhí)行一個(gè)線程方法

          先看這個(gè)

          java.util.concurrent.Executor#execute

          方法實(shí)際執(zhí)行

          io.netty.util.concurrent.SingleThreadEventExecutor#execute(java.lang.Runnable)



          接著執(zhí)行

          io.netty.util.concurrent.SingleThreadEventExecutor#execute(java.lang.Runnable, boolean)



          如上圖所示,這里簡(jiǎn)單描述下這段代碼,

          首先添加前面的addLast方法添加到任務(wù),然后判斷當(dāng)前事件是否輪詢,如果沒(méi)有輪詢,則執(zhí)行if方法體的方法

          這里有個(gè)

          io.netty.util.concurrent.SingleThreadEventExecutor#startThread

          方法,

          跟蹤進(jìn)去



          注意看947行,有個(gè)?

          io.netty.util.concurrent.SingleThreadEventExecutor#doStartThread

          方法,

          跟蹤進(jìn)去


          這里會(huì)通過(guò)線程操作執(zhí)行run方法<上圖989行代碼>

          然后這個(gè)this在這里指代的是什么呢?然后執(zhí)行的run方法又是什么方法呢?

          前面的分析不難看出,設(shè)置的事件輪詢線程組是

          io.netty.channel.nio.NioEventLoopGroup

          所以這里可以猜到,執(zhí)行的應(yīng)該是

          io.netty.channel.nio.NioEventLoop#run

          方法

          看下這幾者之間的類關(guān)系圖



          關(guān)于幾者初始化關(guān)系,會(huì)在后面用圖表示出來(lái),這里先不在詳述

          所以這里執(zhí)行的是

          io.netty.channel.nio.NioEventLoop#run

          即:



          這里的一大段代碼,后面會(huì)詳細(xì)說(shuō)到,目前僅僅做一個(gè)簡(jiǎn)單的介紹,此邏輯類似NIO中,通過(guò)輪詢多路復(fù)用器中每個(gè)通道的不同狀態(tài),然后做不同的事,此邏輯類似的,根據(jù)不同的情況,完成不一樣的邏輯《處理輪詢key,以及數(shù)據(jù)讀寫等等操作》,這里的for循環(huán),是個(gè)死循環(huán),即程序運(yùn)行期間則一直監(jiān)聽(tīng)。


          至此,初始化方法

          io.netty.bootstrap.ServerBootstrap#init

          結(jié)束


          回到

          io.netty.bootstrap.AbstractBootstrap#initAndRegister

          繼續(xù)

          怕忘記了,這里截圖顯示下:



          第311行結(jié)束

          異常情況先不談

          看第323行:

          這里調(diào)用了一個(gè)config方法,然后調(diào)用group方法,在調(diào)用register方法,將前面的Channel注冊(cè)進(jìn)去,這里挨個(gè)詳述源碼:


          config方法


          由于這里是服務(wù)端,則調(diào)用

          io.netty.bootstrap.ServerBootstrap#config

          方法


          這里直接返回一個(gè)config



          簡(jiǎn)單看下這個(gè)

          io.netty.bootstrap.ServerBootstrapConfig


          這里是其簡(jiǎn)單的類關(guān)系圖,這里new一個(gè)ServerBootstrapConfig的時(shí)候傳入了一個(gè)this,簡(jiǎn)單看下,this到底做了什么?

          追蹤到底,這里是給父類

          io.netty.bootstrap.AbstractBootstrapConfig

          的bootstrap賦值




          group方法

          這里能理解到了,這個(gè)group方法,則是調(diào)用

          io.netty.bootstrap.AbstractBootstrapConfig#group

          方法


          返回調(diào)用的是bootstrap.group()方法,這里即調(diào)用

          ServerBootstrapConfig的group方法,然而,在

          ServerBootstrapConfig類中,并沒(méi)有找到對(duì)應(yīng)方法,于是想當(dāng)然的可以去父類中找

          于是在其父類中找到

          io.netty.bootstrap.AbstractBootstrap#group()


          這里是直接返回的一個(gè)group,


          這個(gè)

          io.netty.channel.EventLoopGroup

          則是前面設(shè)置的一個(gè)

          io.netty.channel.nio.NioEventLoopGroup

          即bossGroup


          因?yàn)樵谇懊嬖创a中,這個(gè)EventLoopGroup,才被賦值到

          io.netty.bootstrap.AbstractBootstrapgroup屬性


          最后調(diào)用register方法,則實(shí)質(zhì)調(diào)用的

          io.netty.channel.nio.NioEventLoopGroupregister方法

          然后在NioEventLoopGroup中并沒(méi)有找到這個(gè)方法,則去父類中找

          最后發(fā)現(xiàn)是其父類

          io.netty.channel.MultithreadEventLoopGroup#register(io.netty.channel.Channel)

          中找到方法



          首先這里調(diào)用next()方法,這個(gè)next()方法其實(shí)是調(diào)用父類的next()方法


          io.netty.util.concurrent.MultithreadEventExecutorGroup#next


          如上圖所示,這里的chooser,是初始化階段提到過(guò)的chooser,即2種初始化線程數(shù)量的方法,然后這里可能根據(jù)自身電腦配置不一樣會(huì)有不一樣的

          io.netty.util.concurrent.EventExecutorChooserFactory.EventExecutorChooser

          實(shí)例

          這里可以發(fā)現(xiàn)next方法主要是調(diào)用下一個(gè)線程實(shí)例

          結(jié)合注冊(cè)方法,這里主要將當(dāng)前的這個(gè)

          io.netty.channel.Channel

          注冊(cè)到下一個(gè)線程池里線程實(shí)例中

          這里先簡(jiǎn)單了解下,注冊(cè)到線程實(shí)例的方法,調(diào)用的是

          io.netty.channel.SingleThreadEventLoop#register(io.netty.channel.ChannelPromise)

          方法,即單線程事件輪詢器的注冊(cè)方法


          注冊(cè)完成后,返回一個(gè)

          io.netty.channel.ChannelFuture

          實(shí)例

          到此,初始注冊(cè)方法就先告一段落


          回到前面說(shuō)到的方法:


          前面簡(jiǎn)單簡(jiǎn)述了紅色標(biāo)記的方法,總結(jié)起來(lái)就是構(gòu)建pipeline,初始化相關(guān)參數(shù)信息

          下面上圖接著273行:

          獲取到前面的channel

          下面的其他方法和if判斷邏輯先略過(guò),這里我們主要看281行和299行的doBind0方法

          io.netty.bootstrap.AbstractBootstrap#doBind0

          方法



          如上圖所示,這里是直接將輪詢通道中綁定的事件,執(zhí)行線程方法

          重點(diǎn)看356行:


          調(diào)用

          io.netty.channel.AbstractChannel#bind(java.net.SocketAddress, io.netty.channel.ChannelPromise)

          方法



          繼續(xù)調(diào)用

          io.netty.channel.DefaultChannelPipeline#bind(java.net.SocketAddress, io.netty.channel.ChannelPromise)

          方法



          繼續(xù)調(diào)用

          io.netty.channel.AbstractChannelHandlerContext#bind(java.net.SocketAddress, io.netty.channel.ChannelPromise)

          方法


          這里通過(guò)層層調(diào)用,完成對(duì)端口的監(jiān)聽(tīng)和其他

          io.netty.channel.ChannelPromise

          的操作


          到此結(jié)束分享代碼追蹤層面的Netty服務(wù)端的運(yùn)行邏輯,即什么時(shí)候輪詢,什么時(shí)候執(zhí)行響應(yīng)Task。有一些亂,可以根據(jù)看源碼挨個(gè)挨個(gè)來(lái),后面會(huì)整理下思路和層級(jí)邏輯,畫出類的時(shí)序圖來(lái)幫助理解和消化,本期就先到這兒了,頭有點(diǎn)大.......



          初學(xué),請(qǐng)多指教,歡迎關(guān)注轉(zhuǎn)發(fā).......


          有喜歡的歡迎轉(zhuǎn)發(fā),點(diǎn)擊下面圖片關(guān)注公眾號(hào),不定期更新干貨!


          瀏覽 103
          點(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>
                  免费av在线观影 免费成人毛片网站 | 亚洲免费性爱视频 | 免费看日逼视频情侣 | 艾儿秀拉粑粑原版视频 | 午夜1级操逼视频 |