国产精品电影_久久视频免费_欧美日韩国产激情_成年人视频免费在线播放_日本久久亚洲电影_久久都是精品_66av99_九色精品美女在线_蜜臀a∨国产成人精品_冲田杏梨av在线_欧美精品在线一区二区三区_麻豆mv在线看

原來 Netty 的核心啟動(dòng)邏輯是這樣的!

開發(fā) 前端
bind 的很多方法都是異步執(zhí)行的,所以有些流程是主線程執(zhí)行,有些是 eventloop 執(zhí)行的,這個(gè)需要注意下,不然會(huì)感覺有點(diǎn)亂。

你好,我是yes。

上篇我們已經(jīng)了解了 Netty 的啟動(dòng)流程,還剩一個(gè) bind 方法沒有細(xì)講,這篇我們就著重的說下 bind 方法,這個(gè)方法也是觸發(fā) Netty 真正啟動(dòng)的方法。

先打個(gè)預(yù)防針,源碼也不是那么簡單的,有時(shí)候看著有點(diǎn)繞,如果你想面試的時(shí)候胸有成竹,還是得有點(diǎn)耐心的,如果中間沒看懂沒事,最后我有總結(jié),看完總結(jié)之后應(yīng)該會(huì)清晰的。

對了,如果有條件的話,建議在電腦上看這篇文章,會(huì)更加舒適。

好了,開局先來一張圖,bind 的核心操作就如下圖所示,下面長篇的源碼分析也是為了說清楚這個(gè)流程,所以什么類名,方法名都不重要,重要的是知曉整體流程:

注意,上圖的 Channel 指的是 ServerChannel。

bind 的很多方法都是異步執(zhí)行的,所以有些流程是主線程執(zhí)行,有些是 eventloop 執(zhí)行的,這個(gè)需要注意下,不然會(huì)感覺有點(diǎn)亂。

先看看這張圖大體有個(gè)印象,然后我們開始盤 bind 方法~

bind 流程

從 bind 方法進(jìn)入,實(shí)際上就會(huì)調(diào)用父類 AbstractBootstrap#doBind。

我們來簡單的看下 doBind 這個(gè)方法,要點(diǎn)我都用文字標(biāo)明了:

可以看到,這個(gè)方法主要做了下面這四件事:

  • 創(chuàng)建 channel
  • 初始化 channel
  • 綁定 channel 至 group 內(nèi)的某個(gè) eventLoop 上
  • 綁定端口

下面我會(huì)逐一的分析。

創(chuàng)建 channel

先來看下 initAndRegister 方法。

從下面的源碼可以看到,這個(gè)方法主要就是創(chuàng)建一個(gè) Channel 對象,然后初始化 Channel,最后將它注冊到 eventLoop 上。

channelFactory.newChannel() 是利用反射得到一個(gè) Channel 對象。還記得我們構(gòu)建 ServerBootstrap 時(shí)候設(shè)置的 channel 類型嗎:.channel(NioServerSocketChannel.class)

通過傳入的這個(gè) class 就可以得到構(gòu)造器,然后調(diào)用 newInstance 即可得到一個(gè)對象。

這樣就創(chuàng)建了一個(gè) NioServerSocketChannel 對象。

通過繼承鏈,我們可以發(fā)現(xiàn) NioServerSocketChannel 會(huì)調(diào)用父類 AbstractChannel 的構(gòu)造器,而在這里就會(huì)創(chuàng)建三個(gè)重要的東西:

  • id,channel 的標(biāo)識(shí)
  • unsafe,用來操作底層數(shù)據(jù)讀寫
  • pipeline,handler的編排

所以,從這里可以得知,創(chuàng)建一個(gè) Channel 配套就會(huì)新建一個(gè) pipeline,即每個(gè) Channel 都有自己的 pipeline。

初始化 channel

創(chuàng)建完 Channel 的操作之后,緊接著就初始化 Channel ,即 init() 方法。

可以看到,初始化首先就是把之前在 ServerBootstrap 時(shí)配置的 option 和 attr 塞到已經(jīng)創(chuàng)建的 ServerSocketChannel 中,這個(gè)很好理解。

然后往 ServerSocketChannel 的 pipeline 中塞入一個(gè) ChannelInitializer。

那 ChannelInitializer 是個(gè)什么玩意?它其實(shí)是一個(gè)抽象類,且是一個(gè)入站的 handler。

不過它是一個(gè)特殊的 ChannelHandler ,從 ChannelInitializer 類的注釋就知道:

它的使命就是簡化注冊完畢后的初始化操作,可以理解為是一個(gè)中轉(zhuǎn)的 handler,一個(gè)工具類。它在完成初始化動(dòng)作之后會(huì)從 pipeline 中被移除。

所以,利用 ChannelInitializer 將初始化邏輯封裝起來,當(dāng) channel 注冊到 eventLoop 中之后會(huì)觸發(fā)事件,然后就會(huì)調(diào)用 ChannelInitializer#initChannel 來執(zhí)行初始化,僅此而已。

我們可以看到,上面 initChannel 邏輯是先添加之前配置給 ServerSocketChannel 的 handler,在我們的 helloworld 示例中就是添加 LoggingHandler。

然后再異步添加一個(gè) ServerBootstrapAcceptor 這個(gè) handler,從名字來看,這個(gè) handler 主要是接收處理新連接。

小貼士:此時(shí)的 initChannel 邏輯還未執(zhí)行,是要等到后面事件觸發(fā)了才會(huì)執(zhí)行,且執(zhí)行的線程是 eventLoop 線程。

好了,看到這肯定有人會(huì)有疑問,為什么 initChannel 里面要異步添加 ServerBootstrapAcceptor?

為什么要異步添加 ServerBootstrapAcceptor?不直接添加?

其實(shí)源碼注釋說明的很清楚(上面為了清晰結(jié)構(gòu),把注釋都刪了)

簡單翻譯下,就是用戶可能會(huì)用 ChannelInitializer 來設(shè)置 ServerSocketChannel 的 handler ,注意是ServerSocketChannel 的 handler,不是那個(gè) childHandler 哈。

來看下示例代碼:

  1. // 這樣是沒問題的,不用異步添加 ServerBootstrapAcceptor 
  2.  ServerBootstrap sb = new ServerBootstrap(); 
  3.     sb.channel(...).group(...).childHandler(...).handler(ourHandler); 
  4.      
  5. //這樣的就需要異步添加 ServerBootstrapAcceptor 
  6. ServerBootstrap sb = new ServerBootstrap(); 
  7. sb.channel(...).group(...).childHandler(...).handler( 
  8.     new ChannelInitializer<Channel>() { 
  9.         @Override 
  10.         protected void initChannel(Channel ch) throws Exception { 
  11.             ChannelPipeline pipeline = ch.pipeline(); 
  12.             pipeline.addLast(ourHandler); 
  13.         } 
  14.     } 
  15. ); 

因?yàn)樵诶?ChannelInitializer 設(shè)置 handler 的情況下,initChannel(…)方法只會(huì)在該方法(init 內(nèi)添加ServerBootstrapAcceptor的方法)返回后被調(diào)用。

因此,需要確保以延遲的方式添加,使得用戶定義的 handler 都放在 ServerBootstrapAcceptor 前面。

簡單地說,就是讓 ServerBootstrapAcceptor 成為 ServerSocketChannel 的 pipeline 中最后一個(gè) inboundHandler,這樣用戶定義的 handler 邏輯才會(huì)被調(diào)用到。

因?yàn)楫?dāng)事件傳遞到 ServerBootstrapAcceptor 過就不會(huì)再繼續(xù)通過 pipeline 傳遞了,會(huì)將接待的子 channel 直接分配給 workerGroup了,如果用戶自定義的 handler 在 ServerBootstrapAcceptor 后面的話,里面的邏輯是不會(huì)被執(zhí)行的,等于白加。

不理解的可以多讀幾遍上面的話哈,有一點(diǎn)點(diǎn)小繞。

都說到這了,那就來看看 ServerBootstrapAcceptor 的內(nèi)部邏輯吧。

ServerBootstrapAcceptor 的內(nèi)部邏輯

很簡單,就是根據(jù) selector 得到新連接對應(yīng)的 channel(子channel),然后為其配置之前(初始化ServerBootstrap時(shí))設(shè)置的 childhandler、childoption、childattr,緊接著從 workerGroup 中選擇一個(gè) eventLoop ,將 channel 注冊到這個(gè) eventLoop 上:

這樣,新建的子 channel 之后的所有事件(讀、寫等 I/O 事件),都由從 workerGroup 中選定的那個(gè) eventLoop 負(fù)責(zé)。

至此,我們講完了 init(channel) 的操作。

channel 注冊至 eventLoop

創(chuàng)建且初始化完 channel 之后,就需要把已經(jīng)準(zhǔn)備完畢的 channel 注冊到一個(gè) eventLoop 中。

即上面的ChannelFuture regFuture = config().group().register(channel);(從返回值可以得知這是一個(gè)異步執(zhí)行流程)

這個(gè)動(dòng)作就是從 bossGroup 中選一個(gè) EventLoop ,然后將 channel 注冊到選定的 EventLoop 上。

這個(gè) next() 實(shí)際就是調(diào)用我們之前提到的 chooser 來選擇一個(gè) eventLoop,最終會(huì)將此 eventLoop 傳遞到 AbstractUnsafe#register 中,執(zhí)行注冊邏輯,核心就在這個(gè) register0 方法。

可以看到,無論如何都是由 eventLoop 線程來執(zhí)行 register0 操作(所以對主線程而言,這是異步的)。

我們來看下 register0 都做了什么事:

  • 調(diào)用底層接口,將 channel 注冊到 selector 上
  • 觸發(fā)之前配置的 ChannelInitializer#initChannel
  • 異步添加綁定端口的任務(wù)到 eventLoop 中
  • 觸發(fā) Registered 事件,使之在 pipeline 上傳遞

我們先看第一步 doRegister,看看具體是怎么注冊 Channel 至 Selector 上的。

因?yàn)槲覀兌贾?ServerSocketChannel 是 Netty 定義的類,和 JDK 沒任何關(guān)系,那如何與 JDK 的類適配呢?到底是如何注冊到 JDK 的 Selector 上的呢?

看到我圈起來的地方?jīng)],實(shí)際會(huì)把之前創(chuàng)建的 JDK 的 Channel 注冊到 Selector 上,而 Netty 的 Channel 會(huì)作為一個(gè) attachment 綁定到 JDK 的 Channel 上。

這樣一來,每次 Selector 的時(shí)候,如對應(yīng)的 JDK Channel 有事件發(fā)生,則 Netty 都可以從返回的 JDK Channel 的 attachment 中獲取自己的 Channel,然后觸發(fā)后續(xù)的邏輯,這招叫移花接木。

然后再來看第二步 pipeline.invokeHandlerAddedIfNeeded()。

此時(shí)才會(huì)調(diào)用 ChannelInitializer#initChannel 來添加 handler,且異步提交了一個(gè)添加 ServerBootstrapAcceptor 的任務(wù),隨后將 ChannelInitializer 從 pipeline 中移除。

緊接著就是觸發(fā) Registered 事件,這個(gè)事件會(huì)隨著 pipeline 傳播至所有 handler,只要是入站的 handler,且實(shí)現(xiàn)了下面這個(gè)方法就會(huì)被調(diào)用,所以如果你想在注冊完畢之后做一些邏輯處理,那么就可以創(chuàng)建一個(gè) handler 且實(shí)現(xiàn) channelRegistered 方法。

好了,至此我們終于把 Channel 的創(chuàng)建、初始化、注冊給說完了,后面就是綁定的端口的操作了。

綁定端口

綁定端口主要有兩個(gè)事情需要關(guān)注下,一個(gè)是調(diào)用底層 JDK 綁定端口的實(shí)現(xiàn),二是綁定完之后觸發(fā) active 事件,表明 channel 一切都已就緒。

底層 JDK Channel 的 bind 方法,我就不說了,這個(gè)觸發(fā) active 事件比較關(guān)鍵,最終會(huì)觸發(fā) AbstractNioChannel#doBeginRead,注冊 accept 事件,這樣 ServerSocketChannel 感興趣事件也注冊完畢,可以干活了!

好了,現(xiàn)在我們再來看下這張圖,來對整體的過程捋一捋,至于上面的那些代碼理不清沒事,你只要看懂下面這種圖,知曉大體的流程就夠了:

現(xiàn)在看這張圖是不是有不一樣的感覺?其實(shí)Netty 服務(wù)端的啟動(dòng)流程也就這么回事兒,我再用語言組織一下:

  • 創(chuàng)建 ServerSocketChannel(配套指定一個(gè)ID、底層操作 unsafe對象、pipeline)
  • 將配置的option、attr設(shè)置在創(chuàng)建的 ServerSocketChannel 上
  • 添加一個(gè) ChannelInitializer 至 ServerSocketChannel 的 pipeline 中
  • 從 bossGroup 中選擇一個(gè) eventLoop,將 ServerSocketChannel 與之綁定,且之后生命周期內(nèi)的操作都由這個(gè) eventLoop 執(zhí)行
  • 觸發(fā)第三步添加的 ChannelInitializer 的 initChannel 方法,將用戶配置的 handler 添加到 ServerSocketChannel 的 pipeline 中,且由于需要保證框架內(nèi)置的 ServerBootstrapAcceptor 這個(gè) handler 處于 inboundhandler 的最后一個(gè),因此是異步添加。
  • 觸發(fā) registered 事件,使之在 pipeline 上傳播
  • 調(diào)用 JDK 底層方法,綁定端口
  • 觸發(fā) active 事件,注冊 ServerSocketChannel 感興趣的事件(OP_ACCEPT),用于接收新連接
  • over

最后

好了,我相信通過最后一張圖和最后一段話,你應(yīng)該大致了解了整個(gè) Netty 的啟動(dòng)流程。

如果不明白的話再看看圖,最后是在電腦上看哈,看著代碼應(yīng)該不難理解的,重點(diǎn)就是分清上面的 Channel 指的是 Server 端的 Channel,然后主線程和 eventLoop 線程的執(zhí)行邏輯,有條件的建議自己打斷點(diǎn)試試。

下篇我們將談?wù)?Netty 的 Reactor 模型,這玩意面試被問的幾率好像挺大,如果你還不清楚,沒事,下篇我們慢慢盤!

 

我是 yes,從一點(diǎn)點(diǎn)到億點(diǎn)點(diǎn),我們下篇見~

 

責(zé)任編輯:武曉燕 來源: yes的練級攻略
相關(guān)推薦

2022-05-09 08:37:43

IO模型Java

2020-06-08 17:35:27

Redis集群互聯(lián)網(wǎng)

2022-12-14 07:32:40

InnoDBMySQL引擎

2021-11-10 09:45:06

Lambda表達(dá)式語言

2024-12-17 12:00:00

C++對象模型

2009-03-11 14:42:57

面試求職案例

2023-05-08 07:52:29

JSXReactHooks

2020-05-26 08:52:36

Java JVM多態(tài)

2017-01-16 13:34:21

2022-05-05 08:55:12

工業(yè)物聯(lián)網(wǎng)IIoT

2024-02-06 09:30:25

Figma矩形矩形物理屬性

2023-05-22 15:58:11

2018-04-02 15:13:21

網(wǎng)絡(luò)

2023-02-15 08:17:38

2024-04-30 08:22:51

Figma圖形編輯變換矩陣

2017-01-05 15:07:33

2025-02-17 09:22:16

MySQLSQL語句

2016-10-12 08:54:24

2020-11-24 06:20:02

Linux日志文件系統(tǒng)

2024-05-20 08:45:46

點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號

www.黄在线观看| 精品一区91| 91麻豆.com| 国产精品一区二区三区成人| porn亚洲| 中文字幕日本乱码精品影院| 欧美日韩精品免费观看| 国产一级成人av| 精品国免费一区二区三区| 色婷婷综合网站| 久久精品国产亚洲aⅴ| 日本精品视频在线观看| 97超碰在线公开在线看免费| 亚洲精品中文在线影院| 成人性生活视频免费看| 欧美亚洲视频| 国产精品一区二区久久国产| 欧美综合社区国产| 日韩视频在线你懂得| 丝袜视频国产在线播放| 中文字幕一区三区| 黄色动漫在线免费看| 日本最新不卡在线| 国产精品66部| 五十路熟女丰满大屁股| 国产一区福利| 久久精品99久久久久久久久| 精品国产自在精品国产浪潮| 91精品久久久久久久久久久| 日韩一区二区三区在线| 色多多视频在线播放| 91超碰在线播放| 国产精品99久久久久久久久| 欧美xnxx| 亚洲影院高清在线| 午夜精品电影| 日韩亚洲欧美中文三级| 国产黄色免费在线观看| 日韩一区二区不卡| 亚洲第一成年免费网站| 久久久久看片| 老司机午夜激情| 中文欧美在线视频| 欧美日韩在线观看视频小说| 国内精品久久国产| 欧美午夜片在线免费观看| 91香蕉电影院| 久久91精品久久久久久秒播 | 97中文在线| 亚洲高清激情| 中文网丁香综合网| 国产一区二区导航在线播放| 综合操久久久| 精品久久香蕉国产线看观看亚洲| 玩弄中年熟妇正在播放| 亚洲国产合集| 日本午夜精品一区二区| 国产成人在线影院| 国产一级黄色片免费| 欧美在线一区二区三区| 性欧美超级视频| 日韩在线xxx| 亚洲人成电影在线播放| 91九色鹿精品国产综合久久香蕉| 黄色高清无遮挡| 日韩欧美电影在线| 欧美综合社区国产| 欧美日韩综合精品| 欧美三级中文字| 国产精品美女久久久久高潮| 亚洲成人在线视频网站| 美女视频黄久久| 欧美极品少妇无套实战| 国产区在线观看成人精品| jizzjizzjizz亚洲| 日韩欧美大尺度| 国产视频在线播放| 亚洲毛片一区二区| 亚洲精品一区国产| 国产精品午夜视频| 久久aⅴ国产紧身牛仔裤| 国产一区二区三区在线免费| 国产欧美一区二区在线| 亚洲国产资源| 亚洲精品福利在线观看| 日韩中文字幕| 亚洲qvod图片区电影| 久久三级视频| 亚洲欧美视频二区| 欧美性xxxxxx少妇| 成人自拍视频网| 国产欧美日韩视频| 狠狠色伊人亚洲综合成人| 男人的天堂www| 欧美草草影院在线视频| 一区二区三区四区视频免费观看 | 日本欧美黄色片| 亚洲人成在线观看一区二区| 欧美精品videos另类| 久久精品中文字幕免费mv| 欧美hentaied在线观看| 一区二区日本| 亚洲综合一区二区| 中国色在线日|韩| 国产精品久久久久福利| 麻豆91在线播放| 91网页在线看| 亚洲香蕉成视频在线观看| 成人羞羞网站入口| 无码人妻精品一区二区蜜桃百度| 亚洲一区二区综合| 欧美男女视频| 免费国产一区| 亚洲精品免费视频| 成人影院在线免费观看| 国产精品区二区三区日本| 久久久久久久免费视频了| 97在线观看免费观看高清| 欧美激情一区二区久久久| 久久国产精品久久久久久电车| 邪恶网站在线观看| 日韩av影视综合网| 亚洲欧美亚洲| 99青春婷婷视频| 国产一区二区三区网站| 欧美日韩网址| jizz在亚洲| 亚洲国产成人在线播放| 影视一区二区| 2020中文字幕在线| 亚洲三级黄色在线观看| 亚洲精品三级| 亚洲成人天堂| 人九九综合九九宗合| 99国产精品国产精品久久| 91亚洲天堂| 高清av免费一区中文字幕| 一区二区三区自拍| 97久久亚洲| 久久综合久久网| 欧美变态口味重另类| 中文无码久久精品| 粉嫩tv在线播放| 欧美一级大片在线观看| 国产亚洲福利社区一区| 日本在线一区二区| 毛片av在线播放| 亚洲精品之草原avav久久| 日本不卡一区二区| 顶级网黄在线播放| 黄色99视频| 欧美日韩成人一区二区| 你懂的国产精品永久在线| 992tv成人国产福利在线| 2019亚洲日韩新视频| 久久精品亚洲国产奇米99 | 亚洲欧美日韩国产一区二区三区| 日本免费久久| 色中文字幕在线观看| 精品99一区二区| 亚洲久久一区二区| 欧洲日本在线| 精品国产_亚洲人成在线| 91官网在线观看| 欧美色图麻豆| 婷婷免费在线视频| 国产精品成人观看视频免费| 偷窥国产亚洲免费视频| 国产精品传媒精东影业在线| 亚州av中文字幕在线免费观看| 国产一区二区香蕉| 一本到三区不卡视频| 午夜精品电影| 国产婷婷视频在线| 亚洲国产精品视频一区| 亚洲人午夜色婷婷| 久久综合色8888| 欧美日韩一区二区三区在线电影 | 久久成人久久爱| free欧美| www.色偷偷.com| 欧洲一区二区视频| 欧美视频不卡中文| 亚洲精品社区| 牛牛精品一区二区| 大伊香蕉精品视频在线| 欧美多人爱爱视频网站| 洋洋av久久久久久久一区| 欧美激情亚洲| 在线免费日韩片| 色婷婷综合网站| 成人在线视频电影| 欧美精品一区二区精品网| 国产99精品国产| 国产乱论精品| 久香视频在线观看| 青青草综合视频| 欧美极品少妇xxxxⅹ免费视频| 精品国产福利在线| 国产一区二区三区蝌蚪|