RPC-常见的Netty面试题
1、Netty是什么?
Netty 成功地找到了一种在不妥协可维护性和性能的情况下实现易于开发,性能,稳定性和灵活性的方法。
Netty是一个 基于NIO的client-server(客户端服务器)框架,使用它可以快速简单地开发网络应用程序;- 它极大地简化并优化了
TCP和UDP套接字服务器等网络编程,并且性能以及安全性等很多方面甚至都要更好; Netty在保证快速和易用性的同时,并没有丧失可维护性和性能等优势。- 支持多种协议 如
FTP,SMTP,HTTP以及各种二进制和基于文本的传统协议。
2、Netty的特点是什么?
- 高并发:
Netty是一款基于NIO(Nonblocking IO,非阻塞IO)开发的网络通信框架,对比于BIO(Blocking I/O,阻塞IO),他的并发性能得到了很大提高; - 传输快:
Netty的传输依赖于零拷贝特性,尽量减少不必要的内存拷贝,实现了更高效率的传输; - 封装好:
Netty封装了NIO操作的很多细节,提供了易于使用调用接口。
3、什么是 Netty 的零拷贝?
Netty的接收和发送ByteBuffer采用DIRECT BUFFERS,使用堆外直接内存进行Socket读写,不需要进行字节缓冲区的二次拷贝。如果使用传统的堆内存(HEAP BUFFERS)进行Socket读写,JVM会将堆内存Buffer拷贝一份到直接内存中,然后才写入Socket中。相比于堆外直接内存,消息在发送过程中多了一次缓冲区的内存拷贝;Netty提供了组合Buffer对象,可以聚合多个ByteBuffer对象,用户可以像操作一个Buffer那样方便的对组合Buffer进行操作,避免了传统通过内存拷贝的方式将几个小Buffer合并成一个大的Buffer;Netty的文件传输采用了transferTo方法,它可以直接将文件缓冲区的数据发送到目标Channel,避免了传统通过循环write方式导致的内存拷贝问题。
4、为什么要使用Netty?
- 使用简单:封装了
NIO的很多细节,使用更简单; - 功能强大:预置了多种编解码功能,支持多种主流协议。
- 定制能力强:可以通过
ChannelHandler对通信框架进行灵活地扩展。 - 性能高:通过与其他业界主流的
NIO框架对比,Netty的综合性能最优。 - 稳定:
Netty修复了已经发现的所有NIO的bug,让开发人员可以专注于业务本身。 - 社区活跃:
Netty是活跃的开源项目,版本迭代周期短,bug修复速度快。
5、Netty的应用场景有哪些?
- 作为 RPC 框架的网络通信工具:我们在分布式系统中,不同服务节点之间经常需要相互调用,这个时候就需要
RPC框架了。不同服务节点之间的通信是如何做的呢?可以使用Netty来做。比如我调用另外一个节点的方法的话,至少是要让对方知道我调用的是哪个类中的哪个方法以及相关参数吧! - 实现一个自己的 HTTP 服务器:通过
Netty我们可以自己实现一个简单的HTTP服务器,这个大家应该不陌生。说到HTTP服务器的话,作为Java后端开发,我们一般使用Tomcat比较多。一个最基本的HTTP服务器可要以处理常见的HTTP Method的请求,比如POST请求、GET请求等等。 - 实现一个即时通讯系统:使用
Netty我们可以实现一个可以聊天类似微信的即时通讯系统,这方面的开源项目还蛮多的,可以自行去Github找一找; - 实现消息推送系统:市面上有很多消息推送系统都是基于
Netty来做的。
6、Netty的高性能体现再哪些方面?
- IO 线程模型:同步非阻塞,用最少的资源做更多的事;
- 内存零拷贝:尽量减少不必要的内存拷贝,实现了更高效率的传输;
- 内存池设计:申请的内存可以重用,主要指直接内存。内部实现是用一颗二叉查找树管理内存分配情况;
- 串形化处理读写:避免使用锁带来的性能开销;
- 高性能序列化协议:支持
protobuf等高性能序列化协议。
7、Netty和Tomcat的区别?
- 作用不同:
Tomcat是Servlet容器,可以视为Web服务器,而Netty是异步事件驱动的网络应用程序框架和工具用于简化网络编程,例如TCP和UDP套接字服务器; - 协议不同:
Tomcat是基于http协议的Web服务器,而Netty能通过编程自定义各种协议,因为Netty本身自己能编码/解码字节流,所有Netty可以实现,HTTP服务器、FTP服务器、UDP服务器、RPC服务器、WebSocket服务器、Redis的Proxy服务器、MySQL的Proxy服务器等等。
8、Netty有哪些重要组件?
- Channel:
Netty网络操作抽象类,它除了包括基本的I/O操作,如bind、connect、read、write等; - EventLoop:主要是配合
Channel处理I/O操作,用来处理连接的生命周期中所发生的事情; - ChannelFuture:Netty 框架中所有的
I/O操作都为异步的,因此我们需要ChannelFuture的addListener()注册一个ChannelFutureListener监听事件,当操作执行成功或者失败时,监听就会自动触发返回结果; - ChannelHandler:充当了所有处理入站和出站数据的逻辑容器。
ChannelHandler主要用来处理各种事件,这里的事件很广泛,比如可以是连接、数据接收、异常、数据转换等; - ChannelPipeline:为
ChannelHandler链提供了容器,当channel创建时,就会被自动分配到它专属的ChannelPipeline,这个关联是永久性的。
9、EventloopGroup 和 EventLoop 的关系?
EventLoopGroup包含多个EventLoop(每一个EventLoop通常内部包含一个线程),上面我们已经说了EventLoop的主要作用实际就是负责监听网络事件并调用事件处理器进行相关I/O操作的处理;- 并且
EventLoop处理的I/O事件都将在它专有的Thread上被处理,即Thread和EventLoop属于 1 : 1 的关系,从而保证线程安全; EventLoopGroup包含Boss EventloopGroup和Worker EventloopGroup,其中Boss EventloopGroup用于接收连接,Worker EventloopGroup用于具体的处理(消息的读写以及其他逻辑处理)。
10、Bootstrap 和 ServerBootstrap的区别?
Bootstrap通常使用connet()方法连接到远程的主机和端口,作为一个Netty TCP协议通信中的客户端。另外,Bootstrap也可以通过bind()方法绑定本地的一个端口,作为UDP协议通信中的一端;ServerBootstrap通常使用bind()方法绑定本地的端口上,然后等待客户端的连接;Bootstrap只需要配置一个线程组—EventLoopGroup,而ServerBootstrap需要配置两个线程组—EventLoopGroup,一个用于接收连接,一个用于具体的处理。
11、NioEventLoopGroup 默认的构造函数会起多少线程?
// 1.bossGroup 用于接收连接,workerGroup 用于具体的处理
EventLoopGroup bossGroup = new NioEventLoopGroup(1);
EventLoopGroup workerGroup = new NioEventLoopGroup();
NioEventLoopGroup 默认的构造函数实际会起的线程数为 CPU核心数*2。另外,如果你继续深入下去看构造函数的话,你会发现每个NioEventLoopGroup对象内部都会分配一组NioEventLoop,其大小是 nThreads, 这样就构成了一个线程池, 一个NIOEventLoop 和一个线程相对应,这和我们上面说的 EventloopGroup 和 EventLoop关系这部分内容相对应。
12、Netty 线程模型了解么?
大部分网络框架都是基于 Reactor 模式设计开发的。
12.1、单线程模型
12.2、多线程模型
12.3、主从Reactor模型
13、Netty 服务端和客户端的启动过程了解么?
13.1、Netty 服务端的启动过程?
13.2、Netty 客户端的启动过程?
14、什么是 TCP 粘包/拆包?
15、粘包/拆包的解决办法呢?
15.1、使用 Netty 自带的解码器
- LineBasedFrameDecoder:发送端发送数据包的时候,每个数据包之间以换行符作为分隔,
LineBasedFrameDecoder的工作原理是它依次遍历ByteBuf中的可读字节,判断是否有换行符,然后进行相应的截取; - DelimiterBasedFrameDecoder:可以自定义分隔符解码器,
LineBasedFrameDecoder实际上是一种特殊的DelimiterBasedFrameDecoder解码器; - FixedLengthFrameDecoder:固定长度解码器,它能够按照指定的长度对消息进行相应的拆包。
- LengthFieldBasedFrameDecoder:
15.2、
9、Netty 发送消息有几种方式?
- 直接写入
Channel中,消息从 ChannelPipeline 当中尾部开始移动; - 写入和 ChannelHandler 绑定的 ChannelHandlerContext 中,消息从 ChannelPipeline 中的下一个 ChannelHandler 中移动。
10、Netty默认有多少线程?何时启动?
Netty 默认是 CPU 处理器数的两倍,bind 完之后启动。
11、Netty 支持哪些心跳类型设置?
- readerIdleTime:为读超时时间(即测试端一定时间内未接受到被测试端消息)。
- writerIdleTime:为写超时时间(即测试端一定时间内向被测试端发送消息)。
- allIdleTime:所有类型的超时时间。
浙公网安备 33010602011771号