没有合适的资源?快使用搜索试试~ 我知道了~
16-Netty面试题.docx
0 下载量 63 浏览量
2023-08-22
22:39:58
上传
评论
收藏 478KB DOCX 举报
温馨提示
试读
18页
16-Netty面试题
资源推荐
资源详情
资源评论
1.Netty 是什么?
2.Netty 的特点是什么?
3.Netty 的优势有哪些?
4.Netty 的应用场景有哪些?
5.Netty 高性能表现在哪些方面?
6.BIO、NIO和AIO的区别?
7.NIO的组成?
8.Netty的线程模型?
9.TCP 粘包/拆包的原因及解决方法?
10. 什么是 Netty 的零拷贝?
11. Netty 中有哪种重要组件?
12. Netty 发送消息有几种方式?
13. 默认情况 Netty 起多少线程?何时启动?
14. 了解哪几种序列化协议?
15. 如何选择序列化协议?
16. Netty 支持哪些心跳类型设置?
17. Netty 和 Tomcat 的区别?
18. NIOEventLoopGroup源码?
Netty简介
JDK原生NIO程序的问题
Netty的特点
Netty常见使用场景
Netty高性能设计
I/O模型
阻塞I/O
I/O复用模型
基于buffer
线程模型
事件驱动模型
Reactor线程模型
Netty线程模型
异步处理
Netty架构设计
功能特性
模块组件
Bootstrap、ServerBootstrap
Future、ChannelFuture
Channel
Selector
NioEventLoop
NioEventLoopGroup
ChannelHandler
ChannelHandlerContext
ChannelPipline
工作原理架构
总结
1.Netty 是什么?
Netty是 一个异步事件驱动的网络应用程序框架,用于快速开发可维护的高性能协议服务器和客户端。Netty是基于nio
的,它封装了jdk的nio,让我们使用起来更加方法灵活。
2.Netty 的特点是什么?
高并发:Netty 是一款基于 NIO(Nonblocking IO,非阻塞IO)开发的网络通信框架,对比于 BIO(Blocking I/O,阻塞
IO),他的并发性能得到了很大提高。
传输快:Netty 的传输依赖于零拷贝特性,尽量减少不必要的内存拷贝,实现了更高效率的传输。
封装好:Netty 封装了 NIO 操作的很多细节,提供了易于使用调用接口。
3.Netty 的优势有哪些?
使用简单:封装了 NIO 的很多细节,使用更简单。
功能强大:预置了多种编解码功能,支持多种主流协议。
定制能力强:可以通过 ChannelHandler 对通信框架进行灵活地扩展。性
能高:通过与其他业界主流的 NIO 框架对比,Netty 的综合性能最优。
稳定:Netty 修复了已经发现的所有 NIO 的 bug,让开发人员可以专注于业务本身。
社区活跃:Netty 是活跃的开源项目,版本迭代周期短,bug 修复速度快。
4.Netty 的应用场景有哪些?
典型的应用有:阿里分布式服务框架 Dubbo,默认使用 Netty 作为基础通信组件,还有 RocketMQ 也是使用 Netty 作为
通讯的基础。
5.Netty 高性能表现在哪些方面?
IO 线程模型:同步非阻塞,用最少的资源做更多的事。
内存零拷贝:尽量减少不必要的内存拷贝,实现了更高效率的传输。
内存池设计:申请的内存可以重用,主要指直接内存。内部实现是用一颗二叉查找树管理内存分配情况。
串形化处理读写:避免使用锁带来的性能开销。
高性能序列化协议:支持 protobuf 等高性能序列化协议。
6.BIO、NIO和AIO的区别?
BIO:一个连接一个线程,客户端有连接请求时服务器端就需要启动一个线程进行处理。线程开销大。
伪异步IO:将请求连接放入线程池,一对多,但线程还是很宝贵的资源。
NIO:一个请求一个线程,但客户端发送的连接请求都会注册到多路复用器上,多路复用器轮询到连接有I/O请求时才启
动一个线程进行处理。
AIO:一个有效请求一个线程,客户端的I/O请求都是由OS先完成了再通知服务器应用去启动线程进行处理,
BIO是面向流的,NIO是面向缓冲区的;BIO的各种流是阻塞的。而NIO是非阻塞的;BIO的Stream是单向的,而NIO的
channel是双向的。
NIO的特点:事件驱动模型、单线程处理多任务、非阻塞I/O,I/O读写不再阻塞,而是返回0、基于block的传输比基于
流的传输更高效、更高级的IO函数zero-copy、IO多路复用大大提高了Java网络应用的可伸缩性和实用性。基于Reactor
线程模型。
在Reactor模式中,事件分发器等待某个事件或者可应用或个操作的状态发生,事件分发器就把这个事件传给事先注册的
事件处理函数或者回调函数,由后者来做实际的读写操作。如在Reactor中实现读:注册读就绪事件和相应的事件处理
器、事件分发器等待事件、事件到来,激活分发器,分发器调用事件对应的处理器、事件处理器完成实际的读操作,处
理读到的数据,注册新的事件,然后返还控制权。
7.NIO的组成?
Buffer:与Channel进行交互,数据是从Channel读入缓冲区,从缓冲区写入Channel中的
flip方法 : 反转此缓冲区,将position给limit,然后将position置为0,其实就是切换读写模式
clear方法 :清除此缓冲区,将position置为0,把capacity的值给limit。
rewind方法 : 重绕此缓冲区,将position置为0
DirectByteBuffer可减少一次系统空间到用户空间的拷贝。但Buffer创建和销毁的成本更高,不可控,通常会用内存池来
提高性能。直接缓冲区主要分配给那些易受基础系统的本机I/O 操作影响的大型、持久的缓冲区。如果数据量比较小的中
小应用情况下,可以考虑使用heapBuffer,由JVM进行管理。
Channel:表示 IO 源与目标打开的连接,是双向的,但不能直接访问数据,只能与Buffer 进行交互。通过源码可知,
FileChannel的read方法和write方法都导致数据复制了两次!
Selector可使一个单独的线程管理多个Channel,open方法可创建Selector,register方法向多路复用器器注册通道,可
以监听的事件类型:读、写、连接、accept。注册事件后会产生一个SelectionKey:它表示SelectableChannel 和
Selector 之间的注册关系,wakeup方法:使尚未返回的第一个选择操作立即返回,唤醒的
原因是:注册了新的channel或者事件;channel关闭,取消注册;优先级更高的事件触发(如定时器事件),希望及时
处理。
Selector在Linux的实现类是EPollSelectorImpl,委托给EPollArrayWrapper实现,其中三个native方法是对epoll的封
装,而EPollSelectorImpl. implRegister方法,通过调用epoll_ctl向epoll实例中注册事件,还将注册的文件描述符(fd)与
SelectionKey的对应关系添加到fdToKey中,这个map维护了文件描述符与SelectionKey的映射。
fdToKey有时会变得非常大,因为注册到Selector上的Channel非常多(百万连接);过期或失效的Channel没有及时关
闭。fdToKey总是串行读取的,而读取是在select方法中进行的,该方法是非线程安全的。
Pipe:两个线程之间的单向数据连接,数据会被写到sink通道,从source通道读取
NIO的服务端建立过程:Selector.open():打开一个Selector;ServerSocketChannel.open():创建服务端的
Channel;bind():绑定到某个端口上。并配置非阻塞模式;register():注册Channel和关注的事件到Selector上;
select()轮询拿到已经就绪的事件
8.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只负责接入认
证、握手等操作;
9.TCP 粘包/拆包的原因及解决方法?
TCP是以流的方式来处理数据,一个完整的包可能会被TCP拆分成多个包进行发送,也可能把小的封装成一个大的数据包
发送。
TCP粘包/分包的原因:
应用程序写入的字节大小大于套接字发送缓冲区的大小,会发生拆包现象,而应用程序写入数据小于套接字缓冲区大
小,网卡将应用多次写入的数据发送到网络上,这将会发生粘包现象;
进行MSS大小的TCP分段,当TCP报文长度-TCP头部长度>MSS的时候将发生拆包
以太网帧的payload(净荷)大于MTU(1500字节)进行ip分片。
解决方法
消息定长:FixedLengthFrameDecoder类
包尾增加特殊字符分割:
行分隔符类:LineBasedFrameDecoder
或自定义分隔符类 :DelimiterBasedFrameDecoder
将消息分为消息头和消息体:LengthFieldBasedFrameDecoder类。分为有头部的拆包与粘包、长度字段在前且有头部
的拆包与粘包、多扩展头部的拆包与粘包。
10. 什么是 Netty 的零拷贝?
Netty 的零拷贝主要包含三个方面:
Netty 的接收和发送 ByteBuffer 采用 DIRECT BUFFERS,使用堆外直接内存进行 Socket 读写,不需要进行字节缓冲区的二次
拷贝。如果使用传统的堆内存(HEAP BUFFERS)进行 Socket 读写,JVM 会将堆内存 Buffer 拷贝一份到直接内存中,然后才写入
Socket 中。相比于堆外直接内存,消息在发送过程中多了一次缓冲区的内存拷贝。
Netty 提供了组合 Buffer 对象,可以聚合多个 ByteBuffer 对象,用户可以像操作一个 Buffer 那样方便的对组合 Buffer 进行
操作,避免了传统通过内存拷贝的方式将几个小 Buffer 合并成一个大的 Buffer。
Netty 的文件传输采用了 transferTo 方法,它可以直接将文件缓冲区的数据发送到目标 Channel,避免了传统通过循环 write
方式导致的内存拷贝问题。
11. 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,
这个关联是永久性的。
12. Netty 发送消息有几种方式?
Netty 有两种发送消息的方式:
直接写入 Channel 中,消息从 ChannelPipeline 当中尾部开始移动;
写入和 ChannelHandler 绑定的 ChannelHandlerContext 中,消息从 ChannelPipeline 中的下一个 ChannelHandler 中移
动。
13. 默认情况 Netty 起多少线程?何时启动?
Netty 默认是 CPU 处理器数的两倍,bind 完之后启动。
剩余17页未读,继续阅读
资源评论
毕业程序员
- 粉丝: 8990
- 资源: 1716
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功