Netty面试题
问:netty是什么,解释下。
答:netty是一款基于nio(nonblocking I/O,非阻塞IO)开发的网络通信框架,对比与BIO(Blocking I/O,阻塞IO),并发性能提高很多。而且在快速和易用性的同时,也没有丧失可维护性和性能等优势。
问:netty的特点是什么
答:1.高并发,因为netty是基于nio开发的网络通信框架,并发性得到很大提高。2.传输快,netty的传输依赖于零拷贝特性,尽量避免不必要的内存拷贝,实现了更高效率的传输。3.封装好,netty封装了NIO操作的很多细节,提供了易于使用调用接口。
问:什么是netty的零拷贝
答:netty的零拷贝主要包含三个方面。1,netty的接收和发送bytebuffer采用direct buffers,使用堆外直接内存进行socket读写,不需要进行字节缓冲区的二次拷贝,如果使用传统的堆内存进行socket读写,JVM会将堆内存Buffer拷贝一份到直接内存中,然后才写入socket中,相比于堆外直接内存,消息在发送过程中多了一个缓冲区的内存拷贝。
2.netty提供了组合buffer对象,可以聚合多个bytebuffer对象,用户可以像操作一个buffer那样方便的对组合buffer进行操作,避免了传统通过内存拷贝的方式将几个小buffer合并成一个大的buffer.3.netty的文件传输采用了transferTo方法,可以直接将文件缓冲区的数据发送到目标channel,避免了传统通过循环write方式导致的内存拷贝问题。
问:netty的优势有哪些:
答:1,使用简单,封装了NIO的很多细节,使用更简单。
2.功能强大,预置了多种编解码功能,支持多种主流协议。
3.定制能力强,可以通过channelHandler对通信框架进行灵活的扩展。
4.性能高,通过与其他业界主流的NIO框架对比,Netty的综合性能最优
5.稳定,netty修复了已经发现的所有NIO的bug,让开发人员可以专注于业务本身。
6.社区活跃,Netty是活跃的开源项目,版本迭代周期短,bug修复速度快。
问:netty的使用场景有哪些
答:阿里的分布式服务框架dubbo,默认使用netty作为基础通信组件,rocketmq也是使用netty作为通讯基础。
问:netty的高性能表现在哪些方面。
答:IO线程模型,同步非阻塞,用最少的资源做更多的事。
内存零拷贝,尽量减少不必要的内存拷贝,实现了更高效率的传输。
内存池设计,申请的内存可以重用,主要指直接内存,内部实现是用二叉查找树管理内存分配情况。
串行化处理读写,避免使用锁带来的性能开销。
高性能序列化协议,支持protobuf等高性能序列化协议。
问:netty和tomcat的区别
作用不同:Tomcat 是 Servlet 容器,可以视为 Web 服务器,而 Netty 是异步事件驱动的网络应用程序框架和工具用于简化网络编程,例如TCP和UDP套接字服务器。
协议不同:Tomcat 是基于 http 协议的 Web 服务器,而 Netty 能通过编程自定义各种协议,因为 Netty 本身自己能编码/解码字节流,所以 Netty 可以实现,HTTP 服务器、FTP 服务器、UDP 服务器、RPC 服务器、WebSocket 服务器、Redis 的 Proxy 服务器、MySQL 的 Proxy 服务器等等。
问: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,这个关联是永久性的。
问:netty发送消息有几种方式
答:netty有两种发送消息的方式,1.直接写入channel中,消息从channelPipeline当中尾部开始移动。2.写入和channelHandler绑定的channelHandlerContext中,消息从channelPipeline中的下一个channelHandler中移动。
问:默认netty起多少线程,何时启动
netty默认是CPU处理器数的两倍,bind完之后启动。
问:netty支持哪些心跳类型设置。
readerldleTime:为读超时时间,即测试端一定时间内未接收到被测试端消息
writerldleTime:为写超时时间,即测试端一定时间内向被测试端发送消息
alldleTime:所有类型的超时时间
问:Netty的线程模型
答:Netty通过Reactor模型基于多路复用器接收并处理用户请求,内部实现了两个线程池,boss线程池和work线程池,其中boss线程池的线程负责处理请求的accept事件,当接收到accept事件的请求时,把对应的socket封装到一个NioSocketChannel中,并交给work线程池,其中work线程池负责请求的read和write事件,由对应的Handler处理。
单线程模型:所有I/O操作都由一个线程完成,即多路复用、事件分发和处理都是在一个Reactor线程上完成的。既要接收客户端的连接请求,向服务端发起连接,又要发送/读取请求或应答/响应消息。一个NIO 线程同时处理成百上千的链路,性能上无法支撑,速度慢,若线程进入死循环,整个程序不可用,对于高负载、大并发的应用场景不合适。
多线程模型:有一个NIO 线程(Acceptor) 只负责监听服务端,接收客户端的TCP 连接请求;NIO 线程池负责网络IO 的操作,即消息的读取、解码、编码和发送;1 个NIO 线程可以同时处理N 条链路,但是1 个链路只对应1 个NIO 线程,这是为了防止发生并发操作问题。但在并发百万客户端连接或需要安全认证时,一个Acceptor 线程可能会存在性能不足问题。
主从多线程模型:Acceptor 线程用于绑定监听端口,接收客户端连接,将SocketChannel 从主线程池的Reactor 线程的多路复用器上移除,重新注册到Sub 线程池的线程上,用于处理I/O 的读写等操作,从而保证mainReactor只负责接入认证、握手等操作;
问:TCP 粘包/拆包的原因及解决方法
答:TCP是以流的方式来处理数据,一个完整的包可能会被TCP拆分成多个包进行发送,也可能把小的封装成一个大的数据包发送。
TCP粘包/分包的原因:
应用程序写入的字节大小大于套接字发送缓冲区的大小,会发生拆包现象,而应用程序写入数据小于套接字缓冲区大小,网卡将应用多次写入的数据发送到网络上,这将会发生粘包现象;
进行MSS大小的TCP分段,当TCP报文长度-TCP头部长度>MSS的时候将发生拆包
以太网帧的payload(净荷)大于MTU(1500字节)进行ip分片。
解决方法
消息定长:FixedLengthFrameDecoder类
包尾增加特殊字符分割:行分隔符类:LineBasedFrameDecoder或自定义分隔符类 :DelimiterBasedFrameDecoder
将消息分为消息头和消息体:LengthFieldBasedFrameDecoder类。分为有头部的拆包与粘包、长度字段在前且有头部的拆包与粘包、多扩展头部的拆包与粘包。