1.BIO、NIO和AIO的区别?
BIO:一个请求一个线程 客户端发起连接时就需要启动一个线程处理IO操作,数据的读写必须要阻塞在一个线程中完成,线程开销大
NIO:一个连接一个线程 客户单发起请求注册到多路复用器上,多路复用器轮询到连接然后启动一个线程处理
AIO:一个有效的请求一个线程,客户端发起请求先由OS先完成,再通知服务器应用启动线程处理。它基于事件和回调机制实现的,线程操作不会阻塞,直接返回,等待os通知完成
BIO同步阻塞,面向流;NIO同步非阻塞,面向缓冲区,channel双向的;AIO异步非阻塞。
NIO基于Reactor模型,单线程处理多任务。
Reactor模型:事件分发器等待状态发生变化,事件分发器会将事件交由注册过事件处理函数或回调函数处理
2.NIO的组成?
buffer: 数据从channel读入buffer,从buffer写入channel;直接buffer可减少数据拷贝
channel:双向通道,与目标打卡IO连接,只能与buffer进行交互,不能直接访问。FileChannel的read()和write()方法数据进行了两次拷贝
Selector:选择器,一个线程管理多个channel,register向多路复用器注册通道,监听事件(read,write,accept,connect)变化
channelFuture:
pipe:两个线程之间的连接,是一个链表,数据会被写到sink通道,从source通道读取
4.Netty的线程模型?
Reactor 单线程模型:一个线程处理所有连接和IO读写
Reactor 多线程模型:启动一个Aceptor线程接收连接,再通过NIO线程池处理这个连接所有的IO读写
Reactor 主从多线程模型:一个Aceptor线程监听端口,将SocketChanne从MainReactor线程池的Reactor线程上的多路复用器上移除,重新注册到SubReactor线程池上,进行IO操作,mainReactor只负责接入认证、握手
4.NIO存在的bug,netty怎么解决?
bug:Selector的select方法空轮训问题,导致cpu 100%
解决:netty通过计数器技术周期性记录空轮询次数,在一定的周期内触发N次空轮训,则将Selector
5.TCP 粘包/拆包的原因及解决方法?
原因:tcp基于字节流,应用层和传输层之间的数据交互是大小不等的数据块,但tcp把这些数据块看成一串无结构字节流,无边界。
1、要发送的数据大于TCP发送缓冲区剩余空间大小,将会发生拆包。
2、待发送数据大于MSS(最大报文长度),TCP在传输前将进行拆包。
3、要发送的数据小于TCP发送缓冲区的大小,TCP将多次写入缓冲区的数据一次发送出去,将会发生粘包。
4、接收数据端的应用层没有及时读取接收缓冲区中的数据,将发生粘包
解决:消息数据固定长度(FixedLengthFrameDecoder),但是浪费存储和网络资源
使用分割符来区分包的界限(行分隔符类:LineBasedFrameDecoder或自定义分隔符类 :DelimiterBasedFrameDecoder)
数据包的头部中增加数据包长度字段
UDP基于报文发送,消息头部固定报文长度
6.了解哪几种序列化协议?
xml:可读性好,但占带宽
json:是一种轻量级的数据交换格式,解析速度快,描述性差,
fastjosn:采用一种“假定有序快速匹配”的算法
java默认序列化(Serializable):无法跨平台
7.Netty的零拷贝实现?
使用直接内存,在jvm之外,避免数据的拷贝(内核空间->用户空间)
可以将多个ByteBuffer聚合成一个逻辑上的ByteBuffer,避免传统上的内存拷贝合并
FileChannel.tranferTo文件传输,可以直接将文件缓冲区的数据发送到目标 Channel
8.Netty的高性能表现在哪些方面?
异步非阻塞通信;零拷贝;内存池Buffer(放在堆外,可重复利用);高效的Reactor线程模型;无锁化的串行设计理念;高效的并发编程(使用volatile,CAS和原子类,线程安全容器,读写锁);高性能的序列化框架(默认提供了对Google Protobuf的支持);灵活的TCP参数配置能力
9.NIOEventLoopGroup源码?