1. 程式人生 > >深入淺出Netty:服務啟動

深入淺出Netty:服務啟動

本系列:

本節主要分析server的啟動過程。

Netty是基於Nio實現的,所以也離不開selector、serverSocketChannel、socketChannel和selectKey等,只不過Netty把這些實現都封裝在了底層。

從示例可以看出,一切從ServerBootstrap開始。

ServerBootstrap例項中需要兩個NioEventLoopGroup例項,分別為boss和work,有不同的分工:
1、 boss負責請求的accept操作。
2、 work負責請求的read、write和處理操作。

NioEventLoopGroup

NioEventLoopGroup主要負責管理eventLoop的生命週期,eventLoop數量預設為處理器個數的兩倍。


NioEventLoopGroup

繼承關係如下:


NioEventLoopGroup

NioEventLoopGroup構造方法:

12345678910111213141516 publicNioEventLoopGroup(){this(0);}publicNioEventLoopGroup(intnThreads){this(nThreads,null);}publicNioEventLoopGroup(intnThreads,ThreadFactory threadFactory){this(nThreads,threadFactory,SelectorProvider.provider());}publicNioEventLoopGroup
(intnThreads,ThreadFactory threadFactory,finalSelectorProvider selectorProvider){super(nThreads,threadFactory,selectorProvider);}

MultithreadEventLoopGroup構造方法:

123 protectedMultithreadEventLoopGroup(intnThreads,ThreadFactory threadFactory,Object...args){super(nThreads==0?DEFAULT_EVENT_LOOP_THREADS:nThreads,threadFactory,args);}

其中 DEFAULT_EVENT_LOOP_THREADS 為處理器數量的兩倍。

MultithreadEventExecutorGroup是核心,管理eventLoop的生命週期,先看看其中幾個變數。
1、children:EventExecutor陣列,儲存eventLoop。
2、chooser:從children中選取一個eventLoop的策略。

構造方法:

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263 protectedMultithreadEventExecutorGroup(intnThreads,ThreadFactory threadFactory,Object...args){if(nThreads<=0){thrownewIllegalArgumentException(String.format("nThreads: %d (expected: > 0)",nThreads));}if(threadFactory==null){threadFactory=newDefaultThreadFactory();}children=newSingleThreadEventExecutor[nThreads];if(isPowerOfTwo(children.length)){chooser=newPowerOfTwoEventExecutorChooser();}else{chooser=newGenericEventExecutorChooser();}for(inti=0;i<nThreads;i++){booleansuccess=false;try{children[i]=newChild(threadFactory,args);success=true;}catch(Exceptione){// TODO: Think about if this is a good exception typethrownewIllegalStateException("failed to create a child event loop",e);}finally{if(!success){for(intj=0;j<i;j++){children[j].shutdownGracefully();}for(intj=0;j<i;j++){EventExecutore=children[j];try{while(!e.isTerminated()){e.awaitTermination(Integer.MAX_VALUE,TimeUnit.SECONDS);}}catch(InterruptedException interrupted){Thread.currentThread().interrupt();break;}}}}}finalFutureListener<Object>terminationListener=newFutureListener<Object>(){@OverridepublicvoidoperationComplete(Future<Object>future)throwsException{if(terminatedChildren.incrementAndGet()==children.length){terminationFuture.setSuccess(null);}}};for(EventExecutore:children){e.terminationFuture().addListener(terminationListener);}}protectedEventExecutor newChild(ThreadFactory threadFactory,Object...args)throwsException{returnnewNioEventLoop(this,threadFactory,(SelectorProvider)args[0]);}

1、 根據陣列的大小,採用不同策略初始化chooser。
如果大小為2的冪次方,則採用PowerOfTwoEventExecutorChooser;否則使用GenericEventExecutorChooser。
判斷一個數是否是2的冪次方的方法,覺得很贊。

123 privatestaticbooleanisPowerOfTwo(intval){return(val&-val)==val;}

2、newChild方法過載,初始化EventExecutor時,實際執行的是NioEventLoopGroup中的newChild方法,所以,children元素的實際型別為NioEventLoop。

接下去看看NioEventLoop類。

NioEventLoop

每個eventLoop會維護一個selector和taskQueue,負責處理客戶端請求和內部任務,如ServerSocketChannel註冊和ServerSocket繫結等。


NioEventLoop

繼承關係如下:


NioEventLoop

構造方法:

12345678 NioEventLoop(NioEventLoopGroup parent,ThreadFactory threadFactory,SelectorProvider selectorProvider){super(parent,threadFactory,false);if(selectorProvider==null){thrownewNullPointerException("selectorProvider");}provider=selectorProvider;selector=openSelector();}

當看到 selector = openSelector() 時,有沒有覺得親切了許多,這裡先不管 selector,看看SingleThreadEventLoop類。

SingleThreadEventLoop 構造方法:

123 protectedSingleThreadEventLoop(EventLoopGroup parent,ThreadFactory threadFactory,booleanaddTaskWakesUp){super(parent,threadFactory,addTaskWakesUp);}

啥事都沒做…

SingleThreadEventExecutor
從命名上可以看出,這是一個只有一個執行緒的執行緒池, 先看看其中的幾個變數:
1、state:執行緒池當前的狀態
2、taskQueue:存放任務的佇列
3、thread:執行緒池維護的唯一執行緒
4、scheduledTaskQueue:定義在其父類AbstractScheduledEventExecutor中,用以儲存延遲執行的任務。

構造方法:

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061 protectedSingleThreadEventExecutor(EventExecutorGroup parent,ThreadFactory threadFactory,booleanaddTaskWakesUp){if(threadFactory==null){thrownewNullPointerException("threadFactory");}this.parent=parent;this.addTaskWakesUp=addTaskWakesUp;thread=threadFactory.newThread(newRunnable(){@Overridepublicvoidrun(){booleansuccess=false;updateLastExecutionTime();try{SingleThreadEventExecutor.this.run();success=true;}catch(Throwablet){logger.warn("Unexpected exception from an event executor: ",t);}finally{for(;;){intoldState=STATE_UPDATER.get(SingleThreadEventExecutor.this);if(oldState>=ST_SHUTTING_DOWN||STATE_UPDATER.compareAndSet(SingleThreadEventExecutor.this,oldState,ST_SHUTTING_DOWN)){break;}}// Check if confirmShutdown() was called at the end of the loop.if(success&&gracefulShutdownStartTime==0){logger.error("Buggy "+EventExecutor.class.getSimpleName()+" implementation; "+SingleThreadEventExecutor.class.getSimpleName()+

相關推薦

深入淺出Netty服務啟動

本系列: 本節主要分析server的啟動過程。 Netty是基於Nio實現的,所以也離不開selector、serverSocketChannel、socketChannel和selectKey等,只不過Netty把這些實現都封裝在了底層。 從示例可以看出,一切

mysql配置中吃的虧服務啟動失敗,服務沒有報告任何錯誤

[mysqld] # 設定為自己MYSQL的安裝目錄 basedir=D:\\mysql # 設定為MYSQL的資料目錄 datadir=D:\\mysql\\data default-storage-engine=INNODB character-set

深入淺出Nettywrite

上一章節中,分析了Netty如何處理read事件,本節分析Netty如何把資料寫會客戶端。 把資料返回客戶端,需要經歷三個步驟: 1、申請一塊快取buf,寫入資料。 2、將buf儲存到ChannelOutboundBuffer中。 3、將ChannelOutboundBuffer中的buff輸出到soc

深入淺出NettyNioEventLoop

本系列: 上一章節中,我們分析了Netty服務的啟動過程,本章節分析Netty的eventLoop是如工作的。 NioEventLoop中維護了一個執行緒,執行緒啟動時會呼叫NioEventLoop的run方法,執行I/O任務和非I/O任務。 I/O任務即se

深入淺出NettyChannelPipeline

每個channel內部都會持有一個ChannelPipeline物件pipeline。pipeline預設實現DefaultChannelPipeline內部維護了一個DefaultChannelHandlerContext連結串列。 當channel完成register、active、read等操作時,

深入淺出Nettyread

本系列: boss執行緒主要負責監聽並處理accept事件,將socketChannel註冊到work執行緒的selector,由worker執行緒來監聽並處理read事件,本節主要分析Netty如何處理read事件。 accept->read 當wor

深入淺出Nettyaccept

本系列: 本章節分析服務端如何accept客戶端的connect請求。 在《章節中,已經分析了NioEventLoop的工作機制,當有客戶端connect請求,selector可以返回其對應的SelectionKey,方法processSelectedKeys進行

Flask原始碼分析一服務啟動

前言 Flask是目前為止我最喜歡的一個Python Web框架了,為了更好的掌握其內部實現機制,這兩天準備學習下Flask的原始碼,將由淺入深跟大家分享下,其中Flask版本為1.1.1。 Flask系列文章: Flask開發初探 正文 本文將結合原始碼跟蹤看下Flask是如何啟動並執行一個服務的。 首

Netty原始碼分析服務啟動全過程(篇幅很長)

Netty原始碼分析:服務端啟動全過程 先說結論,Netty 服務端啟動和互動的邏輯的底層實現是藉助於Java NIO ServerSocketChannel來實現,Java NIO ServerSocketChannel作為服務端的繫結埠、接受客戶端的連線的

Netty入門一服務端應用搭建 & 啟動過程原始碼分析

最近週末也沒啥事就學學Netty,同時打算寫一些部落格記錄一下(寫的過程理解更加深刻了) 本文主要從三個方法來呈現:Netty核心元件簡介、Netty服務端建立、Netty啟動過程原始碼分析 如果你對Netty有一定的瞭解, 那閱讀起來應該會比較愉快 ## Netty核心元件簡介 ### ByteBu

windows版redis報錯本地計算機上的Redis服務啟動後停止

col target -c 計算 onf ont font -i 指定 解決 1、如果需要臨時啟動Redis 使用命令:redis-server.exe redis.windows.conf --maxheap 200m 說明:200

Oracle11g啟動Server服務報錯錯誤1053服務沒有及時響應或控制請求

今天 oracle11 alt .com 控制 啟動 oracl 電腦 變量 今日在啟動Oracle11g的服務時,突然莫名報錯,昨日尚一切正常,靜心細思:系統未升級;未安裝其他程序;未更改系統相關配置包括環境變量。 錯誤原因如下圖所示: 經過一番折騰,唯一發現今天特殊點

ZABBIX內存溢出導致zabbix-server/zabbix_server 服務啟動不起來

需求 tor 添加 file ext ram 自己的 rev lease 30964:20180830:105530.520 Starting Zabbix Server. Zabbix 3.4.10 (revision 81503).30964:20180830:1055

Netty(五)ServerBootstrap啟動流程

handle ops pipe 簡單的 inf and acc rest 時也 這篇文章主要是對ServerBootstrap啟動流程做一個梳理,方便我們串聯起各個類,同時也對主要的一些類有個大概的印象,方便之後逐個類的深入學習。 本篇文章不在具體貼出代碼,而是對整個啟動流

IOS推送http2使用netty服務啟動異常

IOS推送http2使用netty服務啟動異常 現象 使用netty開發×××送HTTP2,本機執行正常,部署至linux伺服器異常。 原因 是linux伺服器核心版本過低,所使用GLIBC類庫版本過低。netty要求GLIBC_2.10,我的伺服器最高才GLIBC_2.5。 linux檢視GLIB

eShopOnContainers 看微服務配置 啟動

一、什麼是docker Docker 是一個開源專案,通過把應用程式打包為可移植的、自給自足的容器(可以執行在雲端或本地)的方式,實現應用程式的自動化部署。 使用 Docker 的時候,需要建立一個應用或服務,然後把它和它的依賴打包到一個容器映象中。映象是應用或服務,以及它的配置和依賴的靜態表現形式。要執

java複習筆記2--SpringCloud系列一服務啟動原理探索

微服務架構的趨勢 隨著資料量的不斷增大,大資料時代的到來,網際網路技術的不斷髮展和變革,微服務架構和雲服務平臺以及大資料成為了時下最熱門的話題。現在,比較流行的微服務框架也有很多, 比如阿里的Dubbo,基於soringBoot的SpringCloud,Apac

java複習筆記3--SpringCloud系列一服務啟動原理探之beanFactory載入

昨天,我們對SpringApplication的初始化以及SpringApplication.run方法中的部分程式碼進行了解讀和追蹤。這一塊的重點就是Spring的 SPI,META-INF/spring.factories檔案的格式以及載入機制。一定要花時間

java複習筆記3--SpringCloud系列一服務啟動原理探索之beanFactory載入

昨天,我們對SpringApplication的初始化以及SpringApplication.run方法中的部分程式碼進行了解讀和追蹤。這一塊的重點就是Spring的 SPI,META-INF/spring.factories檔案的格式以及載入機制。一定要花時間

啟動 MySQL服務無法啟動服務沒有報告任何錯誤 - 已解決

下載mysql 8.0.13的壓縮包進行安裝時候報錯,錯誤如下: 報錯 解決辦法 在根目錄放置一個my.ini檔案(my開頭的ini檔案),檔案內容為配置資訊,配置內容如下: [mysql] # 設定mysql客戶端預設字符集 default-character-