螺竹编程
发布于 2024-05-19 / 6 阅读
0

Java面试题/后端框架:Netty面试题

基础

什么是 Netty?它的作用是什么?

Netty 是一个基于 Java NIO 的客户端/服务端网络编程框架,用于快速开发可扩展的网络应用程序。它提供了简单易用的 API,支持事件驱动的异步网络通信,处理高并发和高吞吐量的网络请求。

为何说Netty使用简单?

假设我们现在要搭建一个Server服务器,使用Java NIO的步骤如下:

  1. 创建 ServerSocketChannel。绑定监听端口,并配置为非阻塞模式。

  2. 创建 Selector,将之前创建的 ServerSocketChannel 注册到 Selector 上,监听 SelectionKey.OP_ACCEPT。循环执行 Selector#select() 方法,轮询就绪的 Channel。

  3. 轮询就绪的 Channel 时,如果是处于 OP_ACCEPT 状态,说明是新的客户端接入,调用 ServerSocketChannel#accept()方法,接收新的客户端。设置新接入的 SocketChannel 为非阻塞模式,并注册到 Selector 上,监听 OP_READ 。

  4. 如果轮询的 Channel 状态是 OP_READ ,说明有新的就绪数据包需要读取,则构造 ByteBuffer对象,读取数据。这里,解码数据包的过程,需要我们自己编写。

使用Netty的步骤如下:

  1. 无需关心 OP_ACCEPT、OP_READ、OP_WRITE 等等 IO 操作,Netty 已经封装,对我们在使用是透明无感的。

  2. 使用 boss 和 worker EventLoopGroup ,Netty 直接提供多 Reactor 多线程模型。

  3. 在 Netty 中,我们看到有使用一个解码器 FixedLengthFrameDecoder,可以用于处理定长消息的问题,能够解决 TCP 粘包拆包问题,十分方便。如果使用 Java NIO ,需要我们自行实现解码器。

Netty使用场景?

  1. 构建高性能、低时延的各种 Java 中间件,Netty 主要作为基础通信框架提供高性能、低时延的通信服务。例如:RocketMQ、Dubbo、Spring WebFlux、HDFS。

  2. 公有或者私有协议栈的基础通信框架,例如可以基于 Netty 构建异步、高性能的 WebSocket、Protobuf 等协议的支持。

  3. 各领域应用,例如大数据、游戏等,Netty 作为高性能的通信框架用于内部各模块的数据分发、传输和汇总等,实现模块之间高性能通信。

Netty如何实现高性能?

  1. 线程模型 :更加优雅的 Reactor 模式实现、灵活的线程模型、利用 EventLoop 等创新性的机制,可以非常高效地管理成百上千的 Channel 。

  2. 内存池设计 :使用池化的 Direct Buffer 等技术,在提高 IO 性能的同时,减少了对象的创建和销毁。并且,内吃吃的内部实现是用一颗二叉查找树,更好的管理内存分配情况。

  3. 内存零拷贝 :使用 Direct Buffer ,可以使用 Zero-Copy 机制。

组件及原理

Netty 的核心组件包括哪些?

Netty 的核心组件包括 Channel、EventLoop、ChannelFuture、ChannelHandler、ChannelPipeline、ByteBuf 等。

Netty 的线程模型是什么?为什么它的性能比传统的线程模型更好?

Netty 的线程模型基于 Reactor 模式,采用了单线程 EventLoop 和多线程 EventLoopGroup 的设计。Netty 通过将所有 I/O 操作放到 EventLoop 上执行,避免了线程切换和同步等开销,从而提高了性能和可伸缩性。

Netty中对于TCP黏包、拆包问题的解决?

Netty 可以通过自定义编解码器、使用定长或分隔符解码器等方式来解决粘包和拆包问题。另外,Netty 还提供了 LengthFieldBasedFrameDecoder 这样的通用解码器,可以自动处理消息的长度字段。

TCP 是以流的方式来处理数据,所以会导致粘包 / 拆包。 原因:

  1. 应用程序写入的字节大小大于套接字发送缓冲区的大小,会发生拆包现象。而应用程序写入数据小于套接字缓冲区大小,网卡将应用多次写入的数据发送到网络上,这将会发生粘包现象。

  2. 待发送数据大于 MSS(最大报文长度),TCP 在传输前将进行拆包。

  3. 以太网帧的 payload(净荷)大于 MTU(默认为 1500 字节)进行 IP 分片拆包。

  4. 接收数据端的应用层没有及时读取接收缓冲区中的数据,将发生粘包。

Netty解决: 在 Netty 中,提供了多个 Decoder 解析类,如下:

  1. FixedLengthFrameDecoder ,基于固定长度消息进行粘包拆包处理的。

  2. LengthFieldBasedFrameDecoder ,基于消息头指定消息长度进行粘包拆包处理的。

  3. LineBasedFrameDecoder ,基于换行来进行消息粘包拆包处理的。

  4. DelimiterBasedFrameDecoder ,基于指定消息边界方式进行粘包拆包处理的。

什么是 Channel 和 ChannelPipeline?

Channel 表示一个连接,在 Netty 中用于进行数据读写和事件触发等操作。ChannelPipeline 则是一个 ChannelHandler 的链表,用于处理入站和出站数据,从而实现数据的编解码、协议解析、业务处理等功能。

Netty 支持哪些协议和传输方式?

Netty 支持 TCP、UDP、HTTP、WebSocket 等协议和传输方式,可以用于构建各种类型的网络应用程序。

什么是 EventLoop 和 Future?

EventLoop 是 Netty 中的核心组件,负责处理事件和执行任务。Future 则是异步操作的结果的占位符,可以用于获取操作的执行结果和注册回调函数等操作。

什么是 ByteBuf?与传统的 Java IO 流相比,它有什么优势?

ByteBuf 是 Netty 中的字节缓冲区,用于进行高效的字节操作。与传统的 Java IO 流相比,ByteBuf 支持读写索引分离、零拷贝等优点,可以提高效率和可靠性。

什么是编解码器(Codec)?Netty 中有哪些常用的编解码器?

编解码器(Codec)是一种将消息进行编码和解码的组件,用于将消息从 Java 对象转换为字节流,或将字节流转换为 Java 对象。Netty 中常用的编解码器包括 StringEncoder、StringDecoder、ProtobufEncoder、ProtobufDecoder 等。

如何优化 Netty 应用的性能?

优化 Netty 应用的性能可以从多个方面入手,包括使用合适的线程模型、调整内存池和缓冲区参数、使用零拷贝技术、避免频繁的 GC 等。

Netty 中的哪些组件可以帮助我们实现高可用和容错性?

Netty 中的 ChannelPipeline 和 ChannelHandler 可以帮助我们实现高可用和容错性。通过对请求进行过滤、重试、负载均衡等操作,可以提高系统的可靠性和稳定性。