Netty面试题整理(个人复习)

Netty面试题整理

黑马程序员Netty全套教程,全网最全Netty深入浅出教程,Java网络编程的王者_哔哩哔哩_bilibili

1、什么是Netty?

Netty是基于NIO开发的网络通信框架,使用Netty可以极大的简化TCP和UDP套接字服务器等网络编程,并且性能以及安全性等很多方面都更好。

平常使用的开源框架,Dubbo、RocketMQ、ES等都使用到了Netty。

大部分微服务框架底层涉及到网络通信的部分都是基于Netty来做的。

2、BIO、NIO、AIO的区别?

  • BIO:同步阻塞模式,读取写入数据在同一个线程内阻塞等待完成,客户端数量不高的情况下是没有问题的,但如果是高并发场景下有有些无能为力了。BIO是面向流的,每次从流中读取一定的字节直到读取完全部的数据。
  • NIO:同步非阻塞模式,在Java1.4时引入了对应的java.nio包,它是面向缓冲区的,数据读取到一个缓冲区中,然后对缓冲区的数据进行处理。
  • AIO:在Java7中引入了NIO的改进版NIO2,它是异步非阻塞模型。基于事件和回调机制实现,也就是应用操作之后会直接返回,不会阻塞在那里,当处理完成后操作系统会通知相应的线程进行后续的操作。

3、原生的JavaNIO有什么不足?

NIO的编程模型存在一定的bug,并且编写代码比较复杂,对编程功底有一定的要求。

NIO在面对断线重连、包丢失和粘包问题处理比较复杂,而Netty有更好的解决办法。

4、Netty应用场景

  • 在分布式系统中,作为RPC框架的网络通信工具
  • 可以通过Netty实现一个HTTP服务器
  • 使用Netty实现一个聊天的即时通讯系统。
  • 基于Netty实现消息推送系统。

5、Netty有哪些核心组件?

1)ByteBuf字节容器

网络通信最终都是通过字节流进行传输的,ByteBuf是Netty提供的一个字节容器,内部是一个字节数组,我们通过Netty传输数据时就是通过ByteBuf进行的。

可以把ByteBuf看做是Netty对Java NIO中的ByteBuffer的封装和抽象,因为ByteBuffer这个类使用起来比较复杂,因此Netty对其进行了封装。

2)Bootstrap和ServerBootstrap启动引导类

BootStrap是客户端的启动引导类,ServerBootstrap是服务端的启动引导类。

一个Bootstrap需要一个线程组(EventLoopGroup),而一个ServerBootstrap需要连个线程组,一个负责监听连接事件,另一个用于处理每个接收到的连接。

3)Channel网络操作抽象类

Channel是Netty对网络操作抽象类,通过Channel可以进行IO操作。

当客户端连接到服务端后,就会新建一个Channel与该客户端绑定

常用的Channel接口实现类有:

  • 客户端:NioSocketChannel
  • 服务端:NioServerSocketChannel
4)EventLoop事件循环

EventLoop定义了Netty的核心抽象,用于处理连接的生命周期中所发生的事件。

EventLoop的主要作用实际就是负责监听网络事件并调用事件处理器进行相关的IO操作的处理。

Channel和EventLoop的关系?

Channel为Netty网络操作抽象类,EventLoop负责处理注册到其身上的Channel的IO操作,两个配合进行IO操作。

EventLoopGroup和EventLoop的关系?

EventLoopGroup包含多个EventLoop(每一个EventLoop通常包含一个线程),管理着所有的EventLoop的生命周期。

并且Eventloop处理的IO事件都将在它专有的线程上被处理,即Thread和EventLoop属于1:1的关系,从而保证线程安全。

image-20220221133237066

5)ChannelHandler消息处理器 ChannelPipeline(ChannelHandler对象链表)

ChannelHandler是具体的消息处理器,主要负责处理客户端服务端接收和发送的数据。

当Channel被创建时,它会自动地分配到它专属的ChannelPipeline。一个Channel包含一个ChannelPipeline。ChannelPipeline是ChannelHandler的链,一个pipeline上可以有很多的ChannelHandler。

可以在ChannelPipeline上通过addLast()方法添加一个或者多个ChannelHandler(一个数据或者事件可能会被多个Handler处理)。当一个ChannelHandler处理完之后就会将数据交给下一个ChannelHandler。

当ChannelHandler被添加到ChannelPipeline,它会有一个CHannelHandlerContext,代表一个ChannelHandler和ChannelPipeline之间的“绑定”。ChannelPipeline通过ChannelHandlerContext来间接管理ChannelHandler。

6、ChannelFuture操作执行结果

Netty中所有的IO操作都为异步的,我们不能立刻得到操作是否执行成功。

但是可以通过ChannelFuture接口的addListener()方法注册一个ChannelFutureListener,当操作执行成功或者失败时,监听就会自动触发返回结果。

6、NioEventLoopGroup默认的够咱函数会起多少线程?

实际会起 CPU核心数*2

7、Reactor线程模型

Reactor是一种经典的线程模型,Reactor模式基于事件驱动,特别适合海量的IO事件。

Reactor线程模型分为单线程模型、多线程模型以及主从多线程模型。

  • 单线程Reactor:所有的IO操作都由同一个NIO线程处理。

    单线程Reactor优点是对系统资源消耗特别小,但是没办法支撑大量请求的应用场景并且处理请求的时间可能非常慢。

  • 多线程Reactor:一个线程负责接受请求,一组NIO线程处理IO操作。

    大部分场景下多线程Reactor模型是没有问题的,但是在一个并发连接数较多时一个线程负责接受客户端请求就存在性能问题。

  • 主从多线程Reactor:一组NIO线程负责接受请求,一组NIO线程处理IO操作。

8、什么是TCP粘包、拆包?

TCP粘包、拆包就是基于TCP发送数据时,出现了多个字符串“粘”在了一起或者一个字符串被“拆”开的问题。

解决办法:

  • 使用Netty自带的解码器:

  • 自定义序列化编解码器:在Java中自带的有实现Serializable接口实现序列化,但是由于它性能、安全性等原因一般情况下不使用。

    通常情况下,使用Prorobuff、Hessian2、json序列化方式比较多

9、Netty的长连接、心跳机制了解吗?

TCP长连接和短连接

TCP在进行读写之前,server与client之间必须提前建立一个连接。建立连接的过程,需要三次握手,释放连接时需要四次挥手。这个过程是比较消耗网络资源并且有时间延迟的。

短连接说的就是server端与client端建立连接收,读写完成之后就关闭掉连接,如果下一次再要互相发送消息,就要重新连接。短连接优点很明显,就是管理和实现比较简单,缺点也很明显,每一次的读写都要建立连接必然会带来大量网络资源消耗,并且连接的简历也需要耗费时间。

长连接说的就是client向server双方建立连接之后,即使client与server完成一次读写,他们之间的连接也不会主动关闭,后续的读写操作会继续使用这个连接。长连接可以省去较多的TCP建立和关闭的操作,降低对网络资源的依赖,节约时间。对于拼房请求资源的客户来说,非常适合长连接。

心跳机制

在TCP保持长连接的过程中,可能会出现断网等网络异常出现,异常发生的时候,client与server之间如果没有交互的话,他们是无法发现对方已经掉线的,为了解决这个问题,引入了心跳机制。

心跳机制的工作原理是:在client与server之间在一定时间内没有数据交互时,基础与idle状态时,客户端或服务端就会发送一个特殊的数据包给对方,当接收方收到这个数据报文后,也立即发送一个特殊的数据报文回应给对方,这就是一个PING+PONG交互。所以当某一端收到心跳信息后,就知道对方仍然在线,这就确保了TCP连接的有效性。

TCP实际上自带的就有长连接选项,本身也有心跳包机制,也就是TCP的选项:SO_KEEP_ALIVE。但是,TCP协议层面的长连接灵活性不够,所以,一般情况下我们都是在应用层协议之上实现自定义心跳机制,也就是在Netty层面通过编码实现。通过Netty实现心跳机制,核心类时IdleStateHandler。

10、Netty的零拷贝?

在OS层面上的零拷贝通常指避免在用户态和内核态之间来回拷贝数据,而在Netty层面,零拷贝主要体现在对数据操作的优化。

Netty的接收和发送ByteBuf采用DIRECTBUFFERS,使用堆外直接内存进行Socket读写,不需要进行字节缓冲区的二次拷贝。如果使用传统的堆内存进行Socket读写,JVM会将堆内存Buffer拷贝一份到直接内存中,然后才写入Socket 中。相比于堆外直接内存,消息在发送过程中多了一次缓冲区的内存拷贝。

传统意义的拷贝:

  1. 数据从磁盘读取到内核的readBuffer
  2. 数据从内核缓冲区拷贝到用户缓冲区
  3. 数据从用户缓冲区拷贝到内核的socketbuffer
  4. 数据从内核的socketbuffer拷贝到网卡接口的缓冲区

image-20220221145831961

NIO优化:

通过DirectByteBuf

  • ByteBuffer.allocate(10) HeapByteBuffer使用的是java内存
  • ByteBuffer.allocateDirect(10) DirectByteBuffer使用的是操作系统内存

image-20220221150153328

Java可以使用DirectByteBuffer将堆外内存映射到jvm内存中来直接访问使用。减少了一次数据拷贝,用户态与内核态的切换次数没有减少。

进一步优化

底层代用linux2.1后提供的sendFile方法,java中对应这两个channel调用transferto/transferfrom方法拷贝数据。

image-20220221150555455

java调用transferto方法后,要从java程序的用户态切换到内核态,使用DMA将数据读入内核缓冲区,

数据从内核缓冲区传输到socket缓冲区,cpu会参与拷贝

最后使用DMA将socket缓冲区的数据写入到网卡,不会使用cpu。

可以看到

  • 只发生了一次用户态与内核态的切换
  • 数据拷贝了三次

进一步优化

image-20220221150801372

java调用transferto方法后从java程序的用户态切换到内核态,使用DMA将数据读入内核缓冲区,不会使用CPU。

只会将一些offset和length信息拷入socket缓冲区,几乎无消耗。

使用DMA将内核缓冲区的数据写入网卡。

整个过程只发生了一次用户态与内核态的切换,数据拷贝了两次

所谓的零拷贝,并不是真正的无拷贝,而是在不会拷贝复制数据到jvm内存中。

零拷贝的优点:

  • 更少的用户态与内核态的切换
  • 不利用cpu计算,减少cpu缓存为共享
  • 零拷贝适合小文件传输。

Netty的零拷贝:

  • Netty 提供了CompositeByteBuf类,可以将多个ByteBuf合并为一个逻辑上的ByteBuf,避免了各个ByteBuf之间的拷贝。
  • ByteBuf支持slice操作,可以将ByteBuf分解为多个共享同一个内存区域的ByteBuf,避免了内存拷贝。也就是分片,一个ByteBuf根据索引分为多个ByteBuf,实际上操作的还是同一块内存。
  • 通过FileRegion包装的FileChannel.transferTo实现文件传输,可以直接将文件缓冲区的数据发送到目标channel,避免了传统通过while方式导致的内存拷贝问题。
  • 3
    点赞
  • 36
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1. 什么是NettyNetty是一个高性能、异步事件驱动的网络应用程序框架,用于快速开发可维护的高性能协议服务器和客户端。它基于NIO(Non-blocking I/O)技术,提供了一种高度可定制的网络编程框架。 2. Netty有哪些主要的优点? Netty的主要优点包括: - 高性能:Netty使用异步事件驱动模型,能够处理更高的并发连接数,具有更低的延迟和更高的吞吐量。 - 易于使用:Netty提供了简单、直观的API,使开发人员能够快速上手,快速开发网络应用程序。 - 可扩展性:Netty的设计使其易于扩展,可以通过添加自定义处理器来实现特定的协议或功能。 - 安全性:Netty提供了强大的安全性功能,包括SSL/TLS支持和嵌入式加密。 - 可维护性:Netty的代码结构清晰、模块化,使其易于维护和调试。 3. Netty的核心组件是什么? Netty的核心组件包括: - Channel:表示一个网络连接,可以进行读、写和关闭操作。 - EventLoop:负责处理一个或多个Channel上的事件,包括读、写和空闲事件等。 - ChannelFuture:表示一个异步操作的结果,可以通过添加监听器来处理操作完成后的事件。 - ChannelHandler:用于处理Channel上的事件,包括读、写和异常事件等。 4. Netty的线程模型是什么? Netty的线程模型采用了Reactor模式,它是一种事件驱动的设计模式。在Reactor模式中,有一个或多个EventLoop线程负责处理事件,当有事件发生时,它们会调用相应的处理器来处理事件。 在Netty中,每个Channel都会被注册到一个EventLoop上,当有事件发生时,它们会调用注册在Channel上的ChannelHandler来处理事件。由于EventLoop是单线程的,因此需要通过多个EventLoop来实现并发处理。 5. Netty支持哪些协议? Netty支持多种协议,包括: - TCP/UDP:Netty提供了TCP和UDP协议的实现,支持多种编解码器,可以轻松实现自定义协议。 - HTTP/HTTPS:Netty提供了HTTP和HTTPS协议的实现,可以轻松构建高性能的Web应用程序。 - WebSocket:Netty提供了WebSocket协议的实现,可以轻松构建实时应用程序,如聊天应用程序。 - DNS:Netty提供了DNS协议的实现,可以轻松构建高性能的DNS服务器。 - SMTP:Netty提供了SMTP协议的实现,可以轻松构建高性能的邮件服务器。 - SSH:Netty提供了SSH协议的实现,可以轻松构建安全性高的远程访问应用程序。 6. Netty的内存模型是什么? Netty的内存模型采用了堆外内存池技术,它将Java对象和操作系统的I/O缓冲区分离开来,可以减少Java垃圾回收的负担,提高了性能。 Netty的ByteBuf类用于表示堆外内存,它提供了一种高效的读写字节数据的方式。由于ByteBuf是直接内存,因此可以通过零拷贝技术来减少内存拷贝,提高了性能。 7. 如何优化Netty应用程序的性能? 要优化Netty应用程序的性能,可以采取以下措施: - 使用异步I/O:Netty的异步事件驱动模型可以提高并发连接数、降低延迟和提高吞吐量。 - 精简处理器:只加载必要的处理器,可以减少内存占用和提高性能。 - 合理使用内存:采用堆外内存池技术,可以减少Java垃圾回收的负担,提高性能。 - 使用编解码器:Netty提供了多种编解码器,可以轻松实现自定义协议,提高性能。 - 合理使用线程:合理设置线程数,可以充分利用系统资源,提高性能。 - 使用性能监控工具:可以使用性能监控工具来发现性能瓶颈和优化空间。 8. Netty的异常处理机制是什么? Netty的异常处理机制基于ChannelPipeline,ChannelPipeline中的每个ChannelHandler都可以处理异常。当发生异常时,Netty会将异常抛给最后一个ChannelHandler,并且沿着ChannelPipeline向前传播,直到有处理该异常的ChannelHandler。 如果没有找到能够处理该异常的ChannelHandler,Netty会调用默认的异常处理器,它会将该异常记录到日志中,并关闭该Channel。 9. Netty如何实现心跳机制? Netty可以通过添加IdleStateHandler处理器来实现心跳机制。该处理器会检测Channel是否空闲,如果超过指定的时间没有读或写事件发生,就会触发一个IdleStateEvent事件。开发人员可以通过重写ChannelHandler的userEventTriggered方法来处理该事件,实现心跳机制。 10. Netty如何实现高可用性? 要实现Netty应用程序的高可用性,可以采用以下措施: - 使用负载均衡器:可以通过负载均衡器将请求分发到多个Netty服务器上,提高可用性和吞吐量。 - 实现集群化部署:将Netty应用程序部署到多个服务器上,可以提高可用性和扩展性。 - 配置自动故障转移:在Netty应用程序出现故障时,可以自动将请求转移到备用服务器上,提高可用性。 - 实现数据备份:对于关键数据,可以进行备份,以防止数据丢失。 - 配置监控和告警机制:对于Netty应用程序的关键指标,可以配置监控和告警机制,及时发现和处理故障。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值