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

Netty 線程模型

1. 前言

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

2. Netty 模型介紹

2.1 模型介紹

圖片描述

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

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

2.2 核心概念理解

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

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

3. Netty 模型配置

3.1 單線程配置

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

實例:

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ù)是兩個不同的線程組,負責監(jiān)聽的 acceptor 線程組的線程數(shù)為 1,負責處理客戶端線程組的線程數(shù)大于 1。

實例:

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();//默認是 cpu 的核心數(shù)
        bootstrap.group(acceptorGroup,clientGroup);
    }
}

3.3 主從多線程配置

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

實例:

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

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

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

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

4.1 異步任務(wù)

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

實例:

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

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

4.2 定時任務(wù)

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

實例:

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

    }
}, 60, TimeUnit.SECONDS);

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

總結(jié):

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

5. 小結(jié)

本節(jié)主要掌握的核心知識點

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