欢迎您访问 最编程 本站为您分享编程语言代码,编程技术文章!
您现在的位置是: 首页

Netty面试题集锦(第12期):深入探讨Netty的相关问题

最编程 2024-07-30 15:35:37
...

文章目录

  • 1. 什么是Netty?
  • 2. 为什么要用Netty ?
  • 3. Netty 可以做什么事情?
  • 4. Netty 核心组件了解吗?分别有什么作用?
  • 5. Netty 有几种线程模型?
  • 6. 对于这三种线程Reactor 模型的理解?
    • 6.1 单线程Reactor 模型
    • 6.2 多线程单Reactor 模型
    • 6.2 多线程多Reactor 模型
  • 7. 为什么 Netty 线程池默认大小为 CPU 核数的 2 倍
    • 7.1 如何衡量性能指标

1. 什么是Netty?

  • 第一:Netty 是一个 基于NIO 模型的高性能网络通信框架,其实可以认为它是对NIO 网络模。型的封装,提供了简单易用的API,我们可以利用这些封装好的 API 快速开发自己的网络程序。
  • 第二:Netty 在NIO 的基础上做了很多优化,比如零拷贝机制、高性能无锁队列、内存池等,因此性能会比NIO 更高。
  • 第三:Netty 可以支持多种通信协议,如Http、WebSocket 等,并且针对数据通信的拆包黏包问题,Netty 内置了拆包策略。

2. 为什么要用Netty ?

Netty 相比于直接使用 JDK 自带的 NIO 相关的 API 来说更加易用。同时,它还具有以下特点:

  • 1.统一的API,支持多种传输类型,如阻塞、非阻塞,以及epoll、poll 等模型。
  • 2.我们可以使用非常少的代码来实现,多线程 Reactor 模型以及主从多线程Reactor模型
  • 3.自带编解码器解决TCP 粘包/拆包问题。
  • 4.自带各种协议栈。
  • 5.比直接使用Java 库中的NIO API 有更高的吞吐量、更低的延迟、更低的资源消耗和更少的内存复制。
  • 6.安全性不错,有完整的 SSL/TLS 以及 StartTLS 支持。
  • 7.社区活跃成熟稳定,经历了大型项目的使用和考验,而且很多开源项目都使用到了 Netty, 比如我们经常接触的 Dubbo、RocketMQ 等等。

3. Netty 可以做什么事情?

传统的BIO 模型,由于阻塞的特性,使得在高并发场景中,很难获得更高的吞吐量。而后来基于NIO 的多路复用模型虽然在阻塞方面进行了优化,但是它的 API 使用比较复杂,对于初学者来说使用不是很友好。而 Netty 是基于NIO 的封装,提供了成熟且简单易用的API,降低了使用成本和学习成本。
本质上来说,Netty 和NIO 所扮演的角色是相同的,都是为了提升服务端的吞吐量,让用户获得更好的产品体验。
另外,Netty 这个中间件经过很多年的验证,在目前主流的中间件如 Zookeeper、 Dubbo、RocketMQ 中都有应用。

4. Netty 核心组件了解吗?分别有什么作用?

Netty 由三层结构构成:网络通信层、事件调度器与服务编排层;

  • 在网络通信层有三个核心组件:Bootstrap、ServerBootStrap、Channel

    • Bootstrap 负责客户端启动并用来链接远程netty server
    • ServerBootStrap 负责服务端监听,用来监听指定端口,
    • Channel 是负责网络通信的载体
  • 事件调度器有两个核心组件:EventLoopGroup 与EventLoop

    • EventLoopGroup 本质上是一个线程池,主要负责接收I/O 请求,并分配线程执行处理请求。
    • EventLoop。相当于线程池中的线程
  • 在服务编排层有三个核心组件 ChannelPipeline、ChannelHandler、 ChannelHandlerContext

    • ChannelPipeline 负责将多个Channelhandler 链接在一起
    • ChannelHandler 针对IO 数据的处理器,数据接收后,通过指定的Handler 进行处理。
    • ChannelHandlerContext 用来保存ChannelHandler 的上下文信息

5. Netty 有几种线程模型?

高手Netty 提供了三种Reactor 模型的支持

  • 单线程单Reactor 模型
  • 多线程单Reactor 模型
  • 多线程多Reactor 模型

6. 对于这三种线程Reactor 模型的理解?

Reactor 模型有三个重要的组件:

  • 1.Reactor :将I/O 事件发派给对应的Handler
  • 2.Acceptor :处理客户端连接请求
  • 3.Handlers :执行非阻塞读/写

在这里插入图片描述
其中Reactor 线程,负责多路分离套接字

  • 有新连接到来触发 connect 事件之后,交由Acceptor 进行处理
  • 有 IO 读写事件之后交给 hanlder 处理

Acceptor 主要任务就是构建 handler ,在获取到和client 相关的SocketChannel 之后 ,绑定到相应的 hanlder 上,对应的 SocketChannel 有读写事件之后,基于 racotor分发,hanlder 就可以处理了(所有的IO 事件都绑定到selector 上,有Reactor 分发)

在Reactor 的这种设计中,有三种模型分别是

  • 单线程Reactor 模型。
  • 多线程单Reactor 模型。
  • 多线程多Reactor 模型。

6.1 单线程Reactor 模型

单线程 Reactor 模型,就是由同一个线程来负责处理 IO 事件以及业务逻辑。

这种方式的缺点在于 handler 的执行过程是串行,如果有任何一个 handler 处理线程 阻塞,就会影响整个服务的吞吐量。
在这里插入图片描述

6.2 多线程单Reactor 模型

在这里插入图片描述
也就是把处理IO 就绪事件的线程和处理 Handler 业务逻辑的线程进行分离,每个Handler 由一个独立线程来处理,
在这种设计下,即便是存在 Handler 线程阻塞问题,也不会对IO 线程造成影响。

在多线程Reactor 模型下,所有的 IO 操作都是由一个Reactor 来完成的,而且 Reactor运行在单个线程里面。
对于并发较高的场景下,Reactor 就成为了性能瓶颈,所以在这个基础上做了更进一步优化。提出了多Reactor 多线程模型,这种模式也叫Master-Workers 模式。

6.2 多线程多Reactor 模型

这种模式也叫Master-Workers 模式,它把原本单个Reactor 拆分成了Main Reactor 和多个SubReactor,Main Reactor 负责接收客户端的链接,然后把接收到的连接请求随机分配到多个 subReactor 里面。SubReactor 负责IO 事件的处理。
在这里插入图片描述
这种方式另外一个好处就是可以对 subReactor 做灵活扩展,从而适应不同的并发量,解决了单个Reactor 模式的性能瓶颈问题。

7. 为什么 Netty 线程池默认大小为 CPU 核数的 2 倍

我们都知道使用多线程的本质是为了提升程序的性能,总体来说有两个最核心的指标,一个延迟,一个吞吐量。这两个指标之间有一定的关联,因为同等条件下延迟越短吞吐量越大,但由于它们是不同的维度,一个是时间,一个是空间,并不能相互转换。 因此,提升性能最主要的目的就是要降低延迟,提高吞吐量。

7.1 如何衡量性能指标

具体来说,要降低延时,就是要提高 CPU 的处理能力。而提高吞吐量,就是要提高 IO 读写效率。

那么具体如何衡量系统性能,我从以下两个方面来分析:
我们可以将程序分为是 I/O 密集型任务和CPU 密集型任务。

  • 那么第 1 种情况,对于 CPU 密集型任务而言,理论上“线程的数量 = CPU 核数”就是合适的。但是,在实际应用中的线程数量一般会设置为“CPU 核数 + 1”。因为线程有可能因为内存页失效或其他原因导致阻塞,多设置一个线程可以保证 CPU 的利用率。
  • 第 2 种情况,而对于 I/O 密集型任务而言,我们假设 CPU 计算和I/O 操作的耗时比是 1:1,那么 2 个线程是最合适的。如果 CPU 计算和 I/O 操作的耗时比是 1:2,也就是说 3 个线程是合适的,这样 CPU 和 I/O设备的利用率都可以达到 100%。根据这个推测,我们可以得到这样一个公式:最佳线程数 = 1 +(IO 时/CPU 时)
    不过上面这个公式是针对单核 CPU,如果是多核CPU 只需要等比扩大就可以了,假设 IO 耗时和 CPU 耗时比为 R
    那么计算公式如下:最佳线程数 = CPU 核数 *(1 + R)
  • 而 Netty 的默认线程池个数,就是假设了 I/O 耗时和CPU 耗时的占比是 1:1,实际上 Netty 有一个参数叫 ioRatio,默认为 50,它表示在一个轮事件循环中,单个 I/O 线程执行 I/O 事件和执行异步任务的耗时占比为 1:1。相当于 R = 1,代入上面的公式,就可以得出 Netty 默认设置的线程池大小自然就是 默认线程池大小 = CPU 核数 * (1 + 1) 也就 2 倍 CPU 核数大小。而且 Netty 的应用场景主要是I/O 密集型任务,所以,Netty 这样设计是有科学性的。