Netty
# Netty
# 1.谈一谈BIO、NIO、AIO

客户端数据经过网络传输到服务端机器,一般经过网卡、内核空间、用户空间、服务端程序处理四个步骤。常见的IO模型分为BIO、NIO、AIO三种:
- BIO:只要数据没准备好,则会一直阻塞。
- NIO:解决了数据从网卡写到内核空间阻塞的问题。因此可以通过“程序控制轮询”的方式,查看监视哪个客户端请求的数据已经准备完成,从而衍生了IO多路复用技术。
- AIO:操作系统准备好数据之后,会回调通知服务端程序进行处理。
# 每个请求建立一个线程开销大?——IO多路复用
IO多路复用:单个线程同时处理多个IO请求。在应用程序与内核空间之间,再加一层单线程调用的多路复用程序,不断轮询每个文件描述符是否准备就绪,数据就绪则直接交给对应的程序执行。
# IO多路复用轮询每个文件描述符慢?——epoll
select和poll引入了代理,解决了无事件轮询导致的CPU空转,系统效率低的问题。它可以监视所有流,当有IO事件时唤醒当前线程,当前线程轮询所有文件描述符执行对应的事件。
epoll:解决了多并发连接情况下仅有少数IO事件活跃导致的CPU空转问题。它只会遍历轮询每个发生IO事件的文件描述符,只处理就绪的文件描述符。
# 2.为什么不用NIO而是Netty?Netty的服务端创建流程?
Netty和NIO的区别:
- NIO直接用于开发编程灵活性差。同时不能解决粘包、重连、丢包等问题。
- Netty可以用来作为网络通讯工具,控制节点之间的通信。还可以作为Http服务器。
- Netty给开发者提供更简便的使用方式。同时实现支持多种协议栈。
- Netty经过许多优秀开源项目的考验,Dubbo、RocketMQ等都使用了Netty,性能强大。
Netty服务端创建流程:
- 指定线程数量给EventLoop,确定线程模型。
- 绑定监听的IP和端口。
- 指定消息处理的ChannelHandler对象。
# 3.Reactor模型
Reactor模式基于事件驱动,将对应的事件分发给对应的handler处理。
对于Netty的服务端而言,主要分成两大类操作,分别是接收连接和具体处理操作。其中默认设置线程数量为CPU核心数*2。
单线程模型:一个线程同时负责所有客户端监听和连接、数据处理。(redis)
多线程模型:一个线程处理客户端连接,多个线程(4个)进行数据处理操作。
主从线程模型:多个线程负责客户端监听和连接,多个线程负责数据处理操作。
boss=new NioEventLoopGroup(1);
work=new NioEventLoopGroup(4);
try{
ServerBootstrap b=new ServerBootstrap();
b.group(boss,work);
}
2
3
4
5
6
# 4.什么是粘包,半包问题?
粘包问题:接收到的数据,包含下一个数据包的内容。
半包问题:接收到当前包不完整的数据内容。
产生原因:TCP基于数据流传输数据,因此发送数据时,会根据缓存大小对包大小进行拆分或者是合并。
解决问题的关键在于读取数据时,需要根据传输协议明确每个数据包的开始标志和结束标志。Netty提供了几种不同的编解码器解决这个问题,可以根据换行符划分数据包结束标志符,自定义结束标志符,甚至可以指明数据包长度大小,来读取完整数据包信息。
# 5.长连接和心跳机制
客户端每次和服务端建立连接时,有短连接和长连接两种方式,因为每次建立连接都需要三次握手和四次挥手,比较消耗网络资源。因此对于频繁请求的客户,可以使用长连接,传输完数据继续使用这个连接。
心跳机制是指,每隔一定时间,客户端和服务端之间发送数据包给对方,告诉对方还存活,确保TCP连接的有效性。
# 6.Netty零拷贝
Netty的零拷贝主要体现在对数据操作的优化上:
- CompositeByteBuf可以将多个ByteBuf合并,不需要另外复制。比如将head和body进行合并。
- ByteBuf支持slice操作,将缓冲区分解成多个共享地址的内存区域。