欢迎您的访问
专注于分享最有价值的互联网技术干货

十、Netty 线程模型

几个T的资料等你来白嫖
双倍快乐
资源帮找!!!

Netty 线程模型

1. 前言

前面几节分别讲解了 Reactor 的三种线程模型,都知道主从 Reactor 多线程模型的性能非常的好,那么 Netty 是否就是使用主从 Reactor 多线程模型呢?其实 Netty 线程模型是基于主从 Reactor 多线程模型做了一定的改造,Netty 的线程模型要比 Reactor 主从多线程模型还要复杂。本节主要是通过图解的方式逐步分析 Netty 线程模型的原理。

2. Netty 模型介绍

2.1 模型介绍

20210320204749336.jpg

Netty 模型架构说明:

  1. Netty 抽象出两个线程池,分别是 BossGroup 和 WorkerGroup,BossGroup 专门负责接受客户端的连接,Worker 请求处理;
  2. BossGroup 和 WorkerGroup 类型默认使用的是 NioEventLoopGroup;
  3. NioEventLoopGroup 是一个定时任务线程池,NioEventLoop 是真正工作的线程;
  4. 每个 BossGroup 的 NioEventLoop 分别循环执行三个步骤
    4.1 每个 NioEventLoop 都有一个 Selector,并且不断轮询 accept 事件;
    4.2 处理 accept 事件,与客户端建立连接,生成 NioSocketChannel,并且将其注册到某个 WorkerGroup 下的 NioEventLoop 上的 Selector 上;
    4.3 处理任务队列中的任务,即 runAllTasks。
  5. 每个 WorkerGroup 的 NioEventLoop 分别循环执行三个步骤
    5.1 轮询 read 和 write 事件;
    5.2 处理 I/O 事件,即 read,write 事件,并在其对应的 NioSocketChannel 处理;
    5.3 处理任务队列的任务,即 runAllTasks。

2.2 核心概念理解

Tips: 额外知识点补充,这里提前剧透一下 Channel、ChannelPipeline、ChannelHanlder 之间的关系

  1. 每个客户端连接进来的时候,服务端都会建立一个 Channel;
  2. 为每个 Channel 绑定一个 NioEventLoop 线程,该线程主要负责处理该 Channel 的业务,一个 Channel 对应一个 NioEventLoop,但是一个 NioEventLoop 可以同时服务多个 Channel;
  3. 为每个 Channel 绑定一个 ChannelPipeline,它是一个业务管道,专门负责管理业务链,也就是 ChannelHandler;
  4. WorkerGroup 的核心方法是 runAllTasks (),它主要是触发 NioEventLoop 去处理对应的 Channel 里面的 ChannelPipeline 里面的 ChannelHandler 里面的业务逻辑。

3. Netty 模型配置

3.1 单线程配置

在 ServerBootstrap 调用方法 group 的时候,传递的参数是同一个线程组,且在构造线程组的时候,构造参数为 1。

实例:

public class ServerNetty{
    private ServerBootstrap bootstrap=null;
    private EventLoopGroup group=null;
    public void init(){
        group=new NioEventLoopGroup(1);//线程数量为 1
        bootstrap.group(group,group);
    }
}

3.2 多线程配置

在 ServerBootstrap 调用方法 group 的时候,传递的参数是两个不同的线程组,负责监听的 acceptor 线程组的线程数为 1,负责处理客户端线程组的线程数大于 1。

实例:

public class ServerNetty{
    private ServerBootstrap bootstrap=null;
    private EventLoopGroup acceptorGroup=null;
    private EventLoopGroup clientGroup=null;
    public void init(){
        acceptorGroup=new NioEventLoopGroup(1);//线程数量为 1
        clientGroup=new NioEventLoopGroup();//默认是 cpu 的核心数
        bootstrap.group(acceptorGroup,clientGroup);
    }
}

3.3 主从多线程配置

在 ServerBootstrap 调用方法 group 的时候,传递的参数是两个不同的线程组,负责监听的 acceptor 线程组的线程数大于 1,负责处理客户端线程组的线程数大于 1。

实例:

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

4. 自定义任务队列

通常情况下,任务队列中常见的任务主要有以下几种类型:

  1. 用户自定义的异步任务,比如:依赖线程池去异步某个任务等;
  2. 用户自定义的定时任务,比如:依赖定时线程池去定义每隔 n 秒执行某个任务等;
  3. 非当前 reactor 线程调用 channel 的各种方法。

4.1 异步任务

其实跟我们平时使用线程池没有什么区别,只不过调用的是底层 Netty 线程组。

实例:

//使用 reactor 线程的异步任务
ctx.channel().eventLoop().execute(new Runnable() {
    @Override
    public void run() {
        //...
    }
});

//使用线程池去实现异步任务
ExecutorService es = Executors.newFixedThreadPool(5);
es.execute(new Runnable() {
    @Override
    public void run() {

    }
});

4.2 定时任务

其实类似我们平时使用的定时任务线程池(如:ScheduledThreadPool),只不过是调用底层 Netty 线程组。

实例:

//使用 reactor 线程实现的定时任务
ctx.channel().eventLoop().schedule(new Runnable() {
    @Override
    public void run() {

    }
}, 60, TimeUnit.SECONDS);

//使用线程池去实现定时任务
ScheduledExecutorService ses = Executors.newScheduledThreadPool(5);
ses.schedule(new Runnable() {
    public void run() {
        System.out.println("i:" + temp);
    }
}, 3, TimeUnit.SECONDS);

总结:

  1. 当前 reactor 线程调用当前 eventLoop 执行任务,直接执行,否则,添加到任务队列稍后执行;
  2. netty 内部的任务分为普通任务和定时任务,分别落地到 MpscQueue 和 PriorityQueue;
  3. netty 每次执行任务循环之前,会将已经到期的定时任务从 PriorityQueue 转移到 MpscQueue;
  4. netty 每隔 64 个任务检查一下是否该退出任务循环。

5. 小结

本节主要掌握的核心知识点

  1. Netty 的模型的理解,以及每个 NioEventLoop 所执行的三个核心操作,分别是①轮询出 IO 事件;②处理 IO 事件;③处理任务队列;
  2. 了解 Channel、ChannelPipeline、ChannelHandler 之间的关系,以及 NioEventLoop 主要负责处理每个 Channel 的业务逻辑;
  3. Netty 如何配置三种 Reactor 模型;
  4. 如何使用内置的 NioEventLoop 执行自定义的异步任务和定时任务。
赞(2) 打赏
版权归原创作者所有,任何形式转载请联系我们:大白菜博客 » 十、Netty 线程模型

评论 抢沙发

4 + 6 =
  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏