Netty面试题

一:为什么Netty适合做网络编程?

  1. 使用简单:封闭了 Java 原生 NIO 类库繁琐的 API,使用起来更加高效;
  2. 功能强大:预置多种编码能力,支持多种主流协议。同时通过 ChannelHandler 可以进行灵活的拓展,支持很强的定制能力;
  3. 高性能:与其它业界主流 NIO 框架相比,Netty 综合更优。主要体现在吞吐量更高、延迟更低、减少资源消耗以及最小化不必要的内存复制;
  4. 社区活跃:版本更新周期短,BUG 修复速度快

二:Netty性能好的原因是什么?

  1. 非阻塞I0模型:Netty采用了IO多路复用技术,让多个IO的阻塞复用到一个select线程阻塞上,能够有效的应对大量的并发请求
  2. 高效的Reactor线程模型:支持多种Reactor线程模型,可以根据业务场景的性能诉求,自行选择
  3. 零拷贝:尽量做到不必要的内存拷贝
  4. 内存池设计:使用直接内存,并且可重复利用
  5. 无锁串行化设计:避免使用锁带来的额外开销
  6. 高性能序列化协议:支持 protobuf 等高性能序列化协议

三:Netty的线程模型是怎么样的?

Netty 的线程模型并不是一成不变的,它实际取决于用户的启动参数配置。通过设置不同的启动参数,Netty支持三种模型,分别是Reactor单线程模型、Reactor多线程模型、Reactor主从多线程模型

  1. Reactor单线程模型:一个Reactor既负责处理连接请求,又要负责处理读写请求,一般来说处理连接请求是很快的,但是处理具体的读写请求就要涉及字节的复制,相对慢太多了。Reactor正在处理读写请求的时候,其他请求只能等着,只有等处理完了,才可以处理下一个请求。
  2. Reactor多线程模型:当多个客户端进入服务器后,Reactor线程会监听多种事件,如果监听到连接事件,则把该事件分配给acceptor处理,如果监听到读事件,那么则会发起系统调用,将数据写入内存,之后再把数据交给工作线程池进行业务处理。
    这个时候我们会发现,业务处理的逻辑已经变成多线程处理了。不过一个Reactor既要负责连接事件,又要负责该写事件,同时还要负责数据准备的过程。因为拷贝数据是阻塞的,假如说Reactor阻塞到拷贝数据的时候,服务器进来了很多连接,这个时候,这些连接是很有可能会被服务器拒绝掉的。所以,单个Reactor看来是不够的,我们需要使用多个Reactor来处理。
  3. Reactor主从多线程模型:在主从Reactor模型中,主Reactor线程只负责连接事件的处理,它把读写事件全部交给了子Reactor线程。这样即使在数据准备阶段子线程被阻塞,主Reactor还是可以处理连接事件。

四:Netty的零拷贝是怎么实现的?

Netty的零拷贝模型和操作系统中的零拷贝模型并不完全一样。他主要指的是不需要将数据buffer从一个内存区域拷贝到另一个内存区域。少了一次内存的拷贝,CPU 效率就得到的提升。

  1. 直接使用堆外内存,避免 JVM 堆内存到堆外内存的数据拷贝。
  2. CompositeByteBuf 类,可以组合多个 Buffer 对象合并成一个逻辑上的对象,避免通过传统内存拷贝的方式将几个 Buffer 合并成一个大的 Buffer。
  3. 通过 Unpooled.wrappedBuffer 可以将 byte 数组包装成 ByteBuf 对象,包装过程中不会产生内存拷贝。
  4. ByteBuf.slice 可以将一个 ByteBuf 对象切分成多个ByteBuf 对象,切分过程中不会产生内存拷贝,底层共享一个 byte 数组的存储空间。

五:说说 Netty 的对象池技术?

当我们使用Netty编写一个网络应用程序时,可能需要频繁地创建和释放ByteBuf对象来处理输入和输出数据。如果我们每次需要时都创建新的ByteBuf对象,会导致频繁的垃圾回收和内存分配,降低性能。为了避免这种情况,Netty提供了对象池技术,通过对象池来重用ByteBuf对象,从而减少垃圾回收和内存分配

六:Netty的Buffer为什么好用?

在网络编程中,基本都是基于TCP报文的字节流的操作,所以Java的NIO又新增了ByteBuffer,只不过Java 原生的ByteBuffer,非常难操作,也不能扩缩容,所以Netty又重新封装了自己的Bytebuf,除了性能上的优势之外,Netty的Buffer在使用上相对于NIO也非常简洁,有如下特点:

  1. 动态扩缩容
  2. 读写指针代替#filp

七:能不能说一说Netty的无锁化设计?

  1. Netty基于Reactor线程模式实现并发请求处理,避免了线程阻塞与锁的竞争。
  2. Netty实现了对象池,用来减少对象的创建和销毁,从而也能避免了锁的竞争。
  3. 在Netty中,还有许多组件都被设计为线程安全的,例如,每个Channel都有一个唯一的EventLoop,用于处理所有事件。这样可以避免锁竞争和线程切换带来的开销。

八:Netty如何解决TCP粘包、拆包的问题的?

  1. 短链接,发一个包建立一次连接,这样连接建立到连接断开之间就是消息的边界,缺点:半包还是不好解决,因为接收方的缓冲区大小是有限的
  2. 每一条消息采用固定长度,缺点:数据包的大小不好把握
  3. 每一条消息采用分隔符,例如 \n,缺点:处理字符数据比较合适,但如果内容本身包含了分隔符,那么就会解析错误
  4. 每一条消息分为 head 和 body,head 中包含 body 的长度

九:Netty有哪些序列化协议?

  1. Java原生序列化:Java原生的序列化协议,可以序列化所有实现了Serializable接口的对象。
  2. JSON序列化:JSON是一种轻量级的数据交换格式
  3. XML序列化:XML也是一种常用的数据交换格式
  4. Protobuf序列化:Protobuf是Google开源的一种高效、灵活的二进制序列化协议,具有良好的跨语言能力和高效的序列化性能

你可能感兴趣的:(netty,java)