第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

Netty 線程模型

1. 前言

前面幾節(jié)分別講解了 Reactor 的三種線程模型,都知道主從 Reactor 多線程模型的性能非常的好,那么 Netty 是否就是使用主從 Reactor 多線程模型呢?其實(shí) Netty 線程模型是基于主從 Reactor 多線程模型做了一定的改造,Netty 的線程模型要比 Reactor 主從多線程模型還要復(fù)雜。本節(jié)主要是通過圖解的方式逐步分析 Netty 線程模型的原理。

2. Netty 模型介紹

2.1 模型介紹

圖片描述

Netty 模型架構(gòu)說明:

  1. Netty 抽象出兩個(gè)線程池,分別是 BossGroup 和 WorkerGroup,BossGroup 專門負(fù)責(zé)接受客戶端的連接,Worker 請(qǐng)求處理;
  2. BossGroup 和 WorkerGroup 類型默認(rèn)使用的是 NioEventLoopGroup;
  3. NioEventLoopGroup 是一個(gè)定時(shí)任務(wù)線程池,NioEventLoop 是真正工作的線程;
  4. 每個(gè) BossGroup 的 NioEventLoop 分別循環(huán)執(zhí)行三個(gè)步驟
    4.1 每個(gè) NioEventLoop 都有一個(gè) Selector,并且不斷輪詢 accept 事件;
    4.2 處理 accept 事件,與客戶端建立連接,生成 NioSocketChannel,并且將其注冊(cè)到某個(gè) WorkerGroup 下的 NioEventLoop 上的 Selector 上;
    4.3 處理任務(wù)隊(duì)列中的任務(wù),即 runAllTasks。
  5. 每個(gè) WorkerGroup 的 NioEventLoop 分別循環(huán)執(zhí)行三個(gè)步驟
    5.1 輪詢 read 和 write 事件;
    5.2 處理 I/O 事件,即 read,write 事件,并在其對(duì)應(yīng)的 NioSocketChannel 處理;
    5.3 處理任務(wù)隊(duì)列的任務(wù),即 runAllTasks。

2.2 核心概念理解

Tips: 額外知識(shí)點(diǎn)補(bǔ)充,這里提前劇透一下 Channel、ChannelPipeline、ChannelHanlder 之間的關(guān)系

  1. 每個(gè)客戶端連接進(jìn)來的時(shí)候,服務(wù)端都會(huì)建立一個(gè) Channel;
  2. 為每個(gè) Channel 綁定一個(gè) NioEventLoop 線程,該線程主要負(fù)責(zé)處理該 Channel 的業(yè)務(wù),一個(gè) Channel 對(duì)應(yīng)一個(gè) NioEventLoop,但是一個(gè) NioEventLoop 可以同時(shí)服務(wù)多個(gè) Channel;
  3. 為每個(gè) Channel 綁定一個(gè) ChannelPipeline,它是一個(gè)業(yè)務(wù)管道,專門負(fù)責(zé)管理業(yè)務(wù)鏈,也就是 ChannelHandler;
  4. WorkerGroup 的核心方法是 runAllTasks (),它主要是觸發(fā) NioEventLoop 去處理對(duì)應(yīng)的 Channel 里面的 ChannelPipeline 里面的 ChannelHandler 里面的業(yè)務(wù)邏輯。

3. Netty 模型配置

3.1 單線程配置

在 ServerBootstrap 調(diào)用方法 group 的時(shí)候,傳遞的參數(shù)是同一個(gè)線程組,且在構(gòu)造線程組的時(shí)候,構(gòu)造參數(shù)為 1。

實(shí)例:

public class ServerNetty{
    private ServerBootstrap bootstrap=null;
    private EventLoopGroup group=null;
    public void init(){
        group=new NioEventLoopGroup(1);//線程數(shù)量為 1
        bootstrap.group(group,group);
    }
}

3.2 多線程配置

在 ServerBootstrap 調(diào)用方法 group 的時(shí)候,傳遞的參數(shù)是兩個(gè)不同的線程組,負(fù)責(zé)監(jiān)聽的 acceptor 線程組的線程數(shù)為 1,負(fù)責(zé)處理客戶端線程組的線程數(shù)大于 1。

實(shí)例:

public class ServerNetty{
    private ServerBootstrap bootstrap=null;
    private EventLoopGroup acceptorGroup=null;
    private EventLoopGroup clientGroup=null;
    public void init(){
        acceptorGroup=new NioEventLoopGroup(1);//線程數(shù)量為 1
        clientGroup=new NioEventLoopGroup();//默認(rèn)是 cpu 的核心數(shù)
        bootstrap.group(acceptorGroup,clientGroup);
    }
}

3.3 主從多線程配置

在 ServerBootstrap 調(diào)用方法 group 的時(shí)候,傳遞的參數(shù)是兩個(gè)不同的線程組,負(fù)責(zé)監(jiān)聽的 acceptor 線程組的線程數(shù)大于 1,負(fù)責(zé)處理客戶端線程組的線程數(shù)大于 1。

實(shí)例:

public class ServerNetty{
    private ServerBootstrap bootstrap=null;
    private EventLoopGroup acceptorGroup=null;
    private EventLoopGroup clientGroup=null;
    public void init(){
        acceptorGroup=new NioEventLoopGroup();//默認(rèn)是 cpu 的核心數(shù)
        clientGroup=new NioEventLoopGroup();//默認(rèn)是 cpu 的核心數(shù)
        bootstrap.group(acceptorGroup,clientGroup);
    }
}

4. 自定義任務(wù)隊(duì)列

通常情況下,任務(wù)隊(duì)列中常見的任務(wù)主要有以下幾種類型:

  1. 用戶自定義的異步任務(wù),比如:依賴線程池去異步某個(gè)任務(wù)等;
  2. 用戶自定義的定時(shí)任務(wù),比如:依賴定時(shí)線程池去定義每隔 n 秒執(zhí)行某個(gè)任務(wù)等;
  3. 非當(dāng)前 reactor 線程調(diào)用 channel 的各種方法。

4.1 異步任務(wù)

其實(shí)跟我們平時(shí)使用線程池沒有什么區(qū)別,只不過調(diào)用的是底層 Netty 線程組。

實(shí)例:

//使用 reactor 線程的異步任務(wù)
ctx.channel().eventLoop().execute(new Runnable() {
    @Override
    public void run() {
        //...
    }
});

//使用線程池去實(shí)現(xiàn)異步任務(wù)
ExecutorService es = Executors.newFixedThreadPool(5);
es.execute(new Runnable() {
    @Override
    public void run() {
        
    }
});

4.2 定時(shí)任務(wù)

其實(shí)類似我們平時(shí)使用的定時(shí)任務(wù)線程池(如:ScheduledThreadPool),只不過是調(diào)用底層 Netty 線程組。

實(shí)例:

//使用 reactor 線程實(shí)現(xiàn)的定時(shí)任務(wù)
ctx.channel().eventLoop().schedule(new Runnable() {
    @Override
    public void run() {

    }
}, 60, TimeUnit.SECONDS);

//使用線程池去實(shí)現(xiàn)定時(shí)任務(wù)
ScheduledExecutorService ses = Executors.newScheduledThreadPool(5);
ses.schedule(new Runnable() {
    public void run() {
        System.out.println("i:" + temp);
    }
}, 3, TimeUnit.SECONDS);

總結(jié):

  1. 當(dāng)前 reactor 線程調(diào)用當(dāng)前 eventLoop 執(zhí)行任務(wù),直接執(zhí)行,否則,添加到任務(wù)隊(duì)列稍后執(zhí)行;
  2. netty 內(nèi)部的任務(wù)分為普通任務(wù)和定時(shí)任務(wù),分別落地到 MpscQueue 和 PriorityQueue;
  3. netty 每次執(zhí)行任務(wù)循環(huán)之前,會(huì)將已經(jīng)到期的定時(shí)任務(wù)從 PriorityQueue 轉(zhuǎn)移到 MpscQueue;
  4. netty 每隔 64 個(gè)任務(wù)檢查一下是否該退出任務(wù)循環(huán)。

5. 小結(jié)

本節(jié)主要掌握的核心知識(shí)點(diǎn)

  1. Netty 的模型的理解,以及每個(gè) NioEventLoop 所執(zhí)行的三個(gè)核心操作,分別是①輪詢出 IO 事件;②處理 IO 事件;③處理任務(wù)隊(duì)列;
  2. 了解 Channel、ChannelPipeline、ChannelHandler 之間的關(guān)系,以及 NioEventLoop 主要負(fù)責(zé)處理每個(gè) Channel 的業(yè)務(wù)邏輯;
  3. Netty 如何配置三種 Reactor 模型;
  4. 如何使用內(nèi)置的 NioEventLoop 執(zhí)行自定義的異步任務(wù)和定時(shí)任務(wù)。