跨境互联网 跨境互联网
首页
  • AI 工具

    • 绘图提示词工具 (opens new window)
    • ChatGPT 指令 (opens new window)
  • ChatGPT

    • ChatGP T介绍
    • ChatGPT API 中文开发手册
    • ChatGPT 中文调教指南
    • ChatGPT 开源项目
  • Midjourney

    • Midjourney 文档
  • Stable Diffusion

    • Stable Diffusion 文档
  • 其他

    • AIGC 热门文章
    • 账号合租 (opens new window)
    • 有趣的网站
  • Vue

    • Vue3前置
  • JAVA基础

    • Stream
    • Git
    • Maven
    • 常用第三方类库
    • 性能调优工具
    • UML系统建模
    • 领域驱动设计
    • 敏捷开发
    • Java 测试
    • 代码规范及工具
    • Groovy 编程
  • 并发编程&多线程

    • 并发编程
    • 高性能队列 Disruptor
    • 多线程并发在电商系统下的应用
  • 其他

    • 面试题
  • 消息中间中间件

    • Kafka
    • RabbitMQ
    • RocketMQ
  • 任务调度

    • Quartz
    • XXL-Job
    • Elastic-Job
  • 源码解析

    • Mybatis 高级使用
    • Mybatis 源码剖析
    • Mybatis-Plus
    • Spring Data JPA
    • Spring 高级使用
    • Spring 源码剖析
    • SpringBoot 高级使用
    • SpringBoot 源码剖析
    • Jdk 解析
    • Tomcat 架构设计&源码剖析
    • Tomcat Web应用服务器
    • Zookeeper 高级
    • Netty
  • 微服务框架

    • 分布式原理
    • 分布式集群架构场景化解决方案
    • Dubbo 高级使用
    • Dubbo 核心源码剖析
    • Spring Cloud Gateway
    • Nacos 实战应用
    • Sentinel 实战应用
    • Seata 分布式事务
  • 数据结构和算法的深入应用
  • 存储

    • 图和Neo4j
    • MongoDB
    • TiDB
    • MySQL 优化
    • MySQL 平滑扩容实战
    • MySQL 海量数据存储与优化
    • Elasticsearch
  • 缓存

    • Redis
    • Aerospike
    • Guava Cache
    • Tair
  • 文件存储

    • 阿里云 OSS 云存储
    • FastDF 文件存储
  • 基础

    • Linux 使用
    • Nginx 使用与配置
    • OpenResty 使用
    • LVS+Keepalived 高可用部署
    • Jekins
  • 容器技术

    • Docker
    • K8S
    • K8S
  • 01.全链路(APM)
  • 02.电商终极搜索解决方案
  • 03.电商亿级数据库设计
  • 04.大屏实时计算
  • 05.分库分表的深入实战
  • 06.多维系统下单点登录
  • 07.多服务之间分布式事务
  • 08.业务幂等性技术架构体系
  • 09.高并发下的12306优化
  • 10.每秒100W请求的秒杀架构体系
  • 11.集中化日志管理平台的应用
  • 12.数据中台配置中心
  • 13.每天千万级订单的生成背后痛点及技术突破
  • 14.红包雨的架构设计及源码实现
  • 人工智能

    • Python 笔记
    • Python 工具库
    • 人工智能(AI) 笔记
    • 人工智能(AI) 项目笔记
  • 大数据

    • Flink流处理框架
  • 加密区

    • 机器学习(ML) (opens new window)
    • 深度学习(DL) (opens new window)
    • 自然语言处理(NLP) (opens new window)
AI 导航 (opens new window)

Revin

首页
  • AI 工具

    • 绘图提示词工具 (opens new window)
    • ChatGPT 指令 (opens new window)
  • ChatGPT

    • ChatGP T介绍
    • ChatGPT API 中文开发手册
    • ChatGPT 中文调教指南
    • ChatGPT 开源项目
  • Midjourney

    • Midjourney 文档
  • Stable Diffusion

    • Stable Diffusion 文档
  • 其他

    • AIGC 热门文章
    • 账号合租 (opens new window)
    • 有趣的网站
  • Vue

    • Vue3前置
  • JAVA基础

    • Stream
    • Git
    • Maven
    • 常用第三方类库
    • 性能调优工具
    • UML系统建模
    • 领域驱动设计
    • 敏捷开发
    • Java 测试
    • 代码规范及工具
    • Groovy 编程
  • 并发编程&多线程

    • 并发编程
    • 高性能队列 Disruptor
    • 多线程并发在电商系统下的应用
  • 其他

    • 面试题
  • 消息中间中间件

    • Kafka
    • RabbitMQ
    • RocketMQ
  • 任务调度

    • Quartz
    • XXL-Job
    • Elastic-Job
  • 源码解析

    • Mybatis 高级使用
    • Mybatis 源码剖析
    • Mybatis-Plus
    • Spring Data JPA
    • Spring 高级使用
    • Spring 源码剖析
    • SpringBoot 高级使用
    • SpringBoot 源码剖析
    • Jdk 解析
    • Tomcat 架构设计&源码剖析
    • Tomcat Web应用服务器
    • Zookeeper 高级
    • Netty
  • 微服务框架

    • 分布式原理
    • 分布式集群架构场景化解决方案
    • Dubbo 高级使用
    • Dubbo 核心源码剖析
    • Spring Cloud Gateway
    • Nacos 实战应用
    • Sentinel 实战应用
    • Seata 分布式事务
  • 数据结构和算法的深入应用
  • 存储

    • 图和Neo4j
    • MongoDB
    • TiDB
    • MySQL 优化
    • MySQL 平滑扩容实战
    • MySQL 海量数据存储与优化
    • Elasticsearch
  • 缓存

    • Redis
    • Aerospike
    • Guava Cache
    • Tair
  • 文件存储

    • 阿里云 OSS 云存储
    • FastDF 文件存储
  • 基础

    • Linux 使用
    • Nginx 使用与配置
    • OpenResty 使用
    • LVS+Keepalived 高可用部署
    • Jekins
  • 容器技术

    • Docker
    • K8S
    • K8S
  • 01.全链路(APM)
  • 02.电商终极搜索解决方案
  • 03.电商亿级数据库设计
  • 04.大屏实时计算
  • 05.分库分表的深入实战
  • 06.多维系统下单点登录
  • 07.多服务之间分布式事务
  • 08.业务幂等性技术架构体系
  • 09.高并发下的12306优化
  • 10.每秒100W请求的秒杀架构体系
  • 11.集中化日志管理平台的应用
  • 12.数据中台配置中心
  • 13.每天千万级订单的生成背后痛点及技术突破
  • 14.红包雨的架构设计及源码实现
  • 人工智能

    • Python 笔记
    • Python 工具库
    • 人工智能(AI) 笔记
    • 人工智能(AI) 项目笔记
  • 大数据

    • Flink流处理框架
  • 加密区

    • 机器学习(ML) (opens new window)
    • 深度学习(DL) (opens new window)
    • 自然语言处理(NLP) (opens new window)
AI 导航 (opens new window)
  • Spring Data JPA
  • MyBatis

  • Spring

  • SpringBoot

  • Jdk

  • Tomcat

  • Netty

    • 基础

      • Netty是什么?
      • Netty的高性能设计
        • 2.1、Java中的IO模型
          • 2.1.0、I/0 中的两组概念
          • 2.1.1、BIO模型
          • 2.1.2、NIO模型
          • Buffer(缓冲区):
          • Channel(通道)
          • Selector
          • 2.1.3、AIO模型
        • 2.2、Reactor线程模型
          • 2.2.1、单Reactor单线程模型
          • 2.2.2、单Reactor多线程模型
          • 2.2.3、主从Reactor多线程模型
        • 2.3、Netty模型
          • Netty对三种IO的支持
          • Netty 线程模型其他事项
      • Netty快速入⻔
      • Netty核心组件
      • 详解ByteBuf
    • 进阶

    • 资料
  • 若依

  • Traefik

  • Openresty

  • 开源框架
  • Netty
  • 基础
Revin
2023-06-17
目录

Netty的高性能设计

在本小节中,我们来探索Netty的高性能设计,来了解Netty的性能高在哪里?

要想了解Netty的性能为什么高,就需要从Java的IO模型聊起,然后对网络编程中的Reactor线程模型理 解,Netty就是使用Java的NIO实现了Reactor线程模型,理解这么多内容需要理解很多的概念,下面我 们将一点点的进行学习了解。

# 2.1、Java中的IO模型

# 2.1.0、I/0 中的两组概念

同步/异步,阻塞/非阻塞

在I/O操作中有这么两组概念,其中同步/异步 要和线程中的同步线程/异步线程要区分开,这里指的是同步 IO/异步IO

  • 阻塞/非阻塞:没有数据传过来时,读会阻塞直到有数据;缓冲区满时,写操作也会阻塞。 非阻塞遇到这些情况,都是直接返回。
  • 同步/异步:数据就绪后需要自己去读是同步,数据就绪后系统直接读好再回调给程序是异步。

在JDK1.4之前,基于Java所有的socket通信都采用了同步阻塞模型(BIO),这种模型性能低下,当时 大型的服务均采用C或C++开发,因为它们可以直接使用操作系统提供的异步IO或者AIO,使得性能得到 大幅提升。

2002年,JDK1.4发布,新增了java.nio包,提供了许多异步IO开发的API和类库。新增的NIO,极大的促 进了基于Java的异步非阻塞的发展和应用。

2011年,JDK7发布,将原有的NIO进行了升级,称为NIO2.0,其中也对AIO进行了支持。

# 2.1.1、BIO模型

java中的BIO是blocking I/O的简称,它是同步阻塞型IO,其相关的类和接口在java.io下。 BIO模型简单来讲,就是服务端为每一个请求都分配一个线程进行处理,I/O操作都是基于流Stream的操作

如下:

Page8_01

示例代码:

public class BIOServer
{
    public static void main(String[] args) throws Exception
    {
        ServerSocket serverSocket = new ServerSocket(6666);
        ExecutorService executorService = Executors.newCachedThreadPool();
        while(true)
        {
          System.out.println("等待客户端连接。。。。");
          Socket socket = serverSocket.accept(); //阻塞
          executorService.execute(() - >
              {
                  try
                  {
                      InputStream inputStream = socket.getInputStream(); //阻塞
                      byte[] bytes = new byte[1024];
                      while(true)
                      {
                          int length = inputStream.read(bytes);
                          if(length == -1)
                          {
                              break;
                          }
                          System.out.println(new String(bytes, 0, length, "UTF-8 "));
                              }
                          }
                          catch (Exception e)
                          {
                              e.printStackTrace();
                          }
                      });
              }
          }
      }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34

这种模式存在的问题:

  • 线程开销:客户端的并发数与后端的线程数成1:1的⽐例,线程的创建、销毁是⾮常消耗系统资源的,随着并发量增⼤,服务端性能将显著下降,甚⾄会发⽣线程堆栈溢出等错误。

  • 线程阻塞:当连接创建后,如果该线程没有操作时,会进⾏阻塞操作,这样极⼤的浪费了服务器资源。

# 2.1.2、NIO模型

NIO,称之为New IO 或是 non-block IO (⾮阻塞IO),这两种说法都可以,其实称之为⾮阻塞IO更恰

当⼀些。

NIO相关的代码都放在了java.nio包下,其三⼤核⼼组件:Buffer(缓冲区)、Channel(通道)、

Selector(选择器/多路复⽤器)

# Buffer(缓冲区):

Buffer是一个对象,包含一些要写入或者读出的数据,体现了与原I/O的一个重要区别,在面向流的I/O中,数据读写是直接进入到Steam中,而在NIO中,所有数据都是用缓冲区处理的,读数据直接从缓冲区读,写数据直接写入到缓冲区。

缓冲区的本质是一个数组,通常是一个字节数组(ByteBuffer),也可以使用其他类型,但缓冲区又不仅仅是一个数组,它还提供了对数据结构化访问以及维护读写位置等操作。

在NIO中,所有的读写操作都是基于缓冲区完成的,底层是通过数组实现的,常⽤的缓冲区是ByteBuffer,每⼀种java基本类型都有对应的缓冲区对象(除了Boolean类型),如:CharBuffer、IntBuffer、LongBuffer等。

WM_Netty通信技术进阶_Page6_002

# Channel(通道)

Channel 是一个通道,管道,网络数据通过Channel读取和写入,Channel和流 Stream的不同之处在于Channel是双向的,流只在一个方向上移动(InputStream/OutputStream), 而Channel可以用于读写同时进行,即Channel是全双工的。

在BIO中是基于Stream实现,⽽在NIO中是基于通道实现,与流不同的是,通道是双向的,

既可以读也可以写。

image-20230618151604435

JAVA NIO-Channel

WM_Netty通信技术进阶_Page8_002

						网络读写                                                 文件读写

JAVA NIO-ServerSocketChannel和SocketChannel

image-20230618152442928

image-20230618152634094

# Selector

Selector会不断轮询注册在其上的Channel,如果某个Channel上 面发生读或者写事件,即该Channel处于就绪状态,它就会被Selector轮询出来,然后通过 selectedKeys可以获取就绪Channel的集合,进行后续的I/O操作。

image-20230618152827970

Selector是多路复⽤器,它会不断的轮询注册在其上的Channel,如果某个Channel上发⽣读或写事件,这个Channel就处于就绪状态,会被Selector轮询出来,然后通过SelectionKey获取就绪Channel的集合,进⾏IO的读写操作。

基本示意图如下:

Page9_01

可以看出,NIO模型要优于BIO模型,主要是:

  • 通过多路复⽤器就可以实现⼀个线程处理多个通道,避免了多线程之间的上下⽂切换导致系统开销过⼤。

  • NIO⽆需为每⼀个连接开⼀个线程处理,并且只有通道真正有有事件时,才进⾏读写操作,这样⼤⼤的减少了系统开销。

示例代码:

public class SelectorDemo
{
    /**
    * 注册事件
    * 
    * @return
    */
    private Selector getSelector() throws Exception
    {
        //获取selector对象
        Selector selector = Selector.open();
        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
        serverSocketChannel.configureBlocking(false); //⾮阻塞
        //获取通道并且绑定端⼝
        ServerSocket socket = serverSocketChannel.socket();
        socket.bind(new InetSocketAddress(6677));
        //注册感兴趣的事件
        serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
        return selector;
    }
    public void listen() throws Exception
    {
        Selector selector = this.getSelector();
        while(true)
        {
            selector.select(); //该⽅法会阻塞,直到⾄少有⼀个事件的发⽣
            Set < SelectionKey > selectionKeys = selector.selectedKeys();
            Iterator < SelectionKey > iterator = selectionKeys.iterator();
            while(iterator.hasNext())
            {
                SelectionKey selectionKey = iterator.next();
                process(selectionKey, selector);
                iterator.remove();
            }
        }
    }
    private void process(SelectionKey key, Selector selector) throws Exception
    {
        if(key.isAcceptable())
        { //新连接请求
            ServerSocketChannel server = (ServerSocketChannel) key.channel();
            SocketChannel channel = server.accept();
            channel.configureBlocking(false); //⾮阻塞
            channel.register(selector, SelectionKey.OP_READ);
        }
        else if(key.isReadable())
        { //读数据
            SocketChannel channel = (SocketChannel) key.channel();
            ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
            channel.read(byteBuffer);
            System.out.println("form 客户端 " + new String(byteBuffer.array(), 0, byteBuffer.position()));
        }
    }
    public static void main(String[] args) throws Exception
    {
        new SelectorDemo().listen();
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58

# 2.1.3、AIO模型

在NIO中,Selector多路复⽤器在做轮询时,如果没有事件发⽣,也会进⾏阻塞,如何能把这个阻塞也

优化掉呢?那么AIO就在这样的背景下诞⽣了。

AIO是asynchronous I/O的简称,是异步IO,该异步IO是需要依赖于操作系统底层的异步IO实现。

AIO的基本流程是:⽤户线程通过系统调⽤,告知kernel内核启动某个IO操作,⽤户线程返回。kernel

内核在整个IO操作(包括数据准备、数据复制)完成后,通知⽤户程序,⽤户执⾏后续的业务操作。

  • kernel的数据准备
    • 将数据从⽹络物理设备(⽹卡)读取到内核缓冲区。
  • kernel的数据复制
    • 将数据从内核缓冲区拷⻉到⽤户程序空间的缓冲区。

Page12_01

⽬前AIO模型存在的不⾜:

  • 需要完成事件的注册与传递,这⾥边需要底层操作系统提供⼤量的⽀持,去做⼤量的⼯作。

  • Windows 系统下通过 IOCP 实现了真正的异步 I/O。但是,就⽬前的业界形式来说,Windows 系统,很少作为百万级以上或者说⾼并发应⽤的服务器操作系统来使⽤。

  • ⽽在 Linux 系统下,异步IO模型在2.6版本才引⼊,⽬前并不完善。所以,这也是在 Linux 下,实现⾼并发⽹络编程时都是以 NIO 多路复⽤模型模式为主。

# 2.2、Reactor线程模型

Reactor线程模型不是Java专属,也不是Netty专属,它其实是⼀种并发编程模型,是⼀种思想,具有指

导意义。⽐如,Netty就是结合了NIO的特点,应⽤了Reactor线程模型所实现的。

Reactor模型中定义的三种⻆⾊:

  • Reactor:负责监听和分配事件,将I/O事件分派给对应的Handler。新的事件包含连接建⽴就绪、读就绪、写就绪等。

  • Acceptor:处理客户端新连接,并分派请求到处理器链中。

  • Handler:将⾃身与事件绑定,执⾏⾮阻塞读/写任务,完成channel的读⼊,完成处理业务逻辑后,负责将结果写出channel。

常⻅的Reactor线程模型有三种,如下:

  • Reactor单线程模型

  • Reactor多线程模型

  • 主从Reactor多线程模型

# 2.2.1、单Reactor单线程模型

Page13_01

说明:

  • Reactor充当多路复⽤器⻆⾊,监听多路连接的请求,由单线程完成

  • Reactor收到客户端发来的请求时,如果是新建连接通过Acceptor完成,其他的请求由Handler完成。

  • Handler完成业务逻辑的处理,基本的流程是:Read --> 业务处理 --> Send 。

这种模型的优缺点:

  • 优点

    • 结构简单,由单线程完成,没有多线程、进程通信等问题。

    • 适合⽤在⼀些业务逻辑⽐较简单、对于性能要求不⾼的应⽤场景。

  • 缺点

    • 由于是单线程操作,不能充分发挥多核CPU的性能。

    • 当Reactor线程负载过重之后,处理速度将变慢,这会导致⼤量客户端连接超时,超时之后往往会进⾏重发,这更加重Reactor线程的负载,最终会导致⼤量消息积压和处理超时,成为系统的性能瓶颈。

    • 可靠性差,如果该线程进⼊死循环或意外终⽌,就会导致整个通信系统不可⽤,容易造成单点故障。

# 2.2.2、单Reactor多线程模型

Page14_01

说明:

  • 在Reactor多线程模型相⽐较单线程模型⽽⾔,不同点在于,Handler不会处理业务逻辑,只是负责响应⽤户请求,真正的业务逻辑,在另外的线程中完成。

  • 这样可以降低Reactor的性能开销,充分利⽤CPU资源,从⽽更专注的做事件分发⼯作了,提升整个应⽤的吞吐。

但是这个模型存在的问题:

  • 多线程数据共享和访问⽐较复杂。如果⼦线程完成业务处理后,把结果传递给主线程Reactor进⾏发送,就会涉及共享数据的互斥和保护机制。

  • Reactor承担所有事件的监听和响应,只在主线程中运⾏,可能会存在性能问题。例如并发百万客户端连接,或者服务端需要对客户端握⼿进⾏安全认证,但是认证本身⾮常损耗性能。

为了解决性能问题,产⽣了第三种主从Reactor多线程模型。

# 2.2.3、主从Reactor多线程模型

Page15_01

在主从模型中,将Reactor分成2部分:

  • MainReactor负责监听server socket,⽤来处理⽹络IO连接建⽴操作,将建⽴的socketChannel指定注册给SubReactor。

  • SubReactor主要完成和建⽴起来的socket的数据交互和事件业务处理操作。

这种模式的基本工作流程为:

  • 1)Reactor 主线程 MainReactor 对象通过 select 监听客户端连接事件,收到事件后,通过 Acceptor 处理客户端连接事件。

  • 2)当 Acceptor 处理完客户端连接事件之后(与客户端建立好 Socket 连接),MainReactor 将连接分配给SubReactor。(即:MainReactor 只负责监听客户端连接请求,和客户端建立连接之后将连接交由SubReactor 监听后面的 IO 事件。)

  • 3)SubReactor 将连接加入到自己的连接队列进行监听,并创建 Handler 对各种事件进行处理。

  • 4)当连接上有新事件发生的时候,SubReactor 就会调用对应的 Handler 处理。

  • 5)Handler 通过 read 从连接上读取请求数据,将请求数据分发给 Worker 线程池进行业务处理。

  • 6)Worker 线程池会分配独立线程来完成真正的业务处理,并将处理结果返回给 Handler。Handler 通过send 向客户端发送响应数据。

  • 7)一个 MainReactor 可以对应多个 SubReactor,即一个 MainReactor 线程可以对应多个SubReactor 线程

这种模式的优势如下:

  • 1)MainReactor 线程与 SubReactor 线程的数据交互简单职责明确,MainReactor 线程只需要接收新连接,SubReactor 线程完成后续的业务处理。

  • 2)MainReactor 线程与 SubReactor 线程的数据交互简单, MainReactor 线程只需要把新连接传给SubReactor 线程,SubReactor 线程无需返回数据。

  • 3)多个 SubReactor 线程能够应对更高的并发请求。这种模式的缺点是编程复杂度较高。但是由于其优点明显,在许多项目中被广泛使用,包括 Nginx、Memcached、Netty 等。

这种模式也被叫做服务器的 1+M+N 线程模式,即使用该模式开发的服务器包含一个(或多个,1 只是表示相对较少)连接建立线程+M 个 IO 线程+N 个业务处理线程。这是业界成熟的服务器程序设计模式。

该模型的优点:

  • 响应快,不必为单个同步事件所阻塞,虽然Reactor本身依然是同步的。

  • 可扩展性强,可以⽅便地通过增加SubReactor实例个数来充分利⽤CPU资源。

  • 可复⽤性⾼,Reactor模型本身与具体事件处理逻辑⽆关,具有很⾼的复⽤性。

# 2.3、Netty模型

# Netty对三种IO的支持

image-20230618153641485

Netty模型是基于Reactor模型实现的,对于以上三种模型都有⾮常好的⽀持,也⾮常的灵活,⼀般情

况,在服务端会采⽤主从架构模型,基本示意图如下:

Page15_02

说明:

  • 在Netty模型中,负责处理新连接事件的是BossGroup,负责处理其他事件的是WorkGroup。Group就是线程池的概念。

  • NioEventLoop表示⼀个不断循环的执⾏处理任务的线程,⽤于监听绑定在其上的读/写事件。

  • 通过Pipeline(管道)执⾏业务逻辑的处理,Pipeline中会有多个ChannelHandler,真正的业务逻辑是在ChannelHandler中完成的。

工作流程

  • 1)Netty 抽象出两组线程池:BossGroup和WorkerGroup,每个线程池中都有EventLoop 线程(可以是OIO,NIO,AIO)。BossGroup中的线程专门负责和客户端建立连接,WorkerGroup中的线程专门负责处理连接上的读写, EventLoopGroup 相当于一个事件循环组,这个组中含有多个事件循环
  • 2)EventLoop 表示一个不断循环的执行事件处理的线程,每个EventLoop 都包含一个 Selector,用于监听注册在其上的 Socket 网络连接(Channel)。
  • 3)每个 Boss EventLoop 中循环执行以下三个步骤:
    • 3.1)select:轮训注册在其上的 ServerSocketChannel 的 accept 事件(OP_ACCEPT 事件)
    • 3.2)processSelectedKeys:处理 accept 事件,与客户端建立连接,生成一个SocketChannel,并将其注册到某个 WorkerEventLoop 上的 Selector 上
    • 3.3)runAllTasks:再去以此循环处理任务队列中的其他任务
  • 4)每个 Worker EventLoop 中循环执行以下三个步骤:
    • 4.1)select:轮训注册在其上的SocketChannel 的 read/write 事件(OP_READ/OP_WRITE 事件)
    • 4.2)processSelectedKeys:在对应的SocketChannel 上处理 read/write 事件
    • 4.3)runAllTasks:再去以此循环处理任务队列中的其他任务
  • 5)在以上两个processSelectedKeys步骤中,会使用 Pipeline(管道),Pipeline 中引用了 Channel,即通过 Pipeline 可以获取到对应的 Channel,Pipeline 中维护了很多的处理器(拦截处理器、过滤处理器、自定义处理器等)。

# Netty 线程模型其他事项

  • 1)Netty 的线程模型基于主从多Reactor模型。通常由一个线程负责处理OP_ACCEPT事件,拥有 CPU 核数的两倍的IO线程处理读写事件
  • 2)一个通道的IO操作会绑定在一个IO线程中,而一个IO线程可以注册多个通道
  • 3)在一个网络通信中通常会包含网络数据读写,编码、解码、业务处理。默认情况下网络数据读写,编码、解码等操作会在IO线程中运行,但也可以指定其他线程池。
  • 4)通常业务处理会单独开启业务线程池(看业务类型),但也可以进一步细化,例如心跳包可以直接在IO线程中处理,而需要再转发给业务线程池,避免线程切换
  • 5)在一个IO线程中所有通道的事件是串行处理的。
  • 6)通常业务操作会专门开辟一个线程池,那业务处理完成之后,如何将响应结果通过 IO 线程写入到网卡中呢?业务线程调用 Channel对象的 write 方法并不会立即写入网络,只是将数据放入一个待写入缓存区,然后IO线程每次执行事件选择后,会从待写入缓存区中获取写入任务,将数据真正写入到网络中
上次更新: 2025/04/03, 11:07:08
Netty是什么?
Netty快速入⻔

← Netty是什么? Netty快速入⻔→

最近更新
01
tailwindcss
03-26
02
PaddleSpeech
02-18
03
whisper
02-18
更多文章>
Theme by Vdoing | Copyright © 2019-2025 跨境互联网 | 豫ICP备14016603号-5 | 豫公网安备41090002410995号
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式