Netty是是什么?
Netty是基于NIO的客户,服务器端的编程框架,它提供了异步的、事件驱动的网络应用程序框架和工具,用以快速开发高性能、高可靠的网络服务器和客户端程序。
Netty有什么特点?

IO模型
BIO
同步阻塞IO,服务器实现模式为一个连接一个线程,即客户端有连接请求时服务器端就需要启动一个线程进行处理。适用于连接数目比较小且固定的架构,这种方式对服务器资源要求比较高,并发局限于应用中。
BIO是针对字节流和字符流的处理。
NIO
同步非阻塞,服务器实现模式为一个线程处理多个请求,即客户端发送的连接请求都会注册到多路复用器上,多路复用器轮询到连接有IO请求就进行处理。适用于连接数目多且连接短的架构。
NIO是针对Channel和Buffer的处理。
AIO
异步非阻塞,AIO引入异步通道的概念,采用Proactor模式,简化了程序编写,有效的请求才启动线程,它的特点是由操作系统完成后才通知服务端程序启动线程去处理,一般适用于连接数较多且连接时间较长的应用。
通道(Channel)和流有什么区别?
- 通道是双向的,而流是单向的。
- 通道可以实现异步读写数据
- 通道可以从缓冲区读数据,也可以写数据到缓冲区。
什么是零拷贝?
零拷贝是指计算机操作的过程中,CPU不需要为数据在内存之间的拷贝消耗资源。通常它是指计算机在网络上发送文件时,不需要将文件内容拷贝到用户空间,而直接在内核空间中传输到网络的方式,接收亦然。
零拷贝是网络编程的关键,许多性能优化都离不开。
在Java程序中常用的零拷贝有mmap(内存映射)和sendFile。
内存映射时间文件映射到内核缓冲区,同时用户空间可以共享内核空间的数据。
sendFile是linux2.1版本提供的一个新的函数,其原理是数据不经过用户态,直接从内核缓冲区直接进入到socket buffer,同时,由于和用户态完全无关,就减少了异常上下文切换。
NIO可以直接将一个通道中的数据传递(transferTo)到另一个通道,而不经过buffer实际就是零拷贝。
多路复用模式Reactor和Proactor是什么,有什么区别?
在Reactor中,事件分离器负责等待文件描述符或者socket为读写操作准备就绪,然后将就绪事件传递给对应的处理器,最后由处理器负责完成实际的读写工作。本质就是IO事件触发时,通知我们主动去读取,也就是要我们主动将socket接收缓存中的数据读到应用进程内存中。
而在Proactor模式中,处理器或者事件分离器,只负责发起异步读写操作。IO操作本身由操作系统来完成。本质是当有数据包到达时,则写入到应用进程内的指定的buffer,然后通知我们接收了多少个字节。
简单来讲就是Reactor关心就绪事件,比如可读了,就通知你。而Proactor关心的是完成,比如读完了,就通知你。
为什么非阻塞IO更快速、更经济?
- 非阻塞网络调用使得我们可以不比等待一个操作完成。
- 选择器使得我们能够使用更少的线程便可以监视许多连接上的事件。
Netty的核心组件
Channel
Channel是Java NIO的一个基本构造,它代表一个到实体的开发连接,如读操作和写操作。
回调
一个回调其实就是一个方法,一个指向已经被提供给另外一个方法的方法的引用。这使得后者可以在适当的时候调用前者。
Future
Future提供了另一种子在操作完成时通知引用程序的方式。这个对象可以看作时一个异步操作的占位符;它将在未来的某个时刻完成,并提供对其结果的访问。
相比与jdk中的Future,Netty自己实现了ChannelFuture,用于在执行异步操作的时候使用。
事件和Channelhandler
Netty使用不同的事件来通知我们状态的改变或者是操作的状态。这使得我们能够基于已经发送的事件来触发适当的动作。
Netty是一个网络编程框架,所以事件是按照它们与入展或出站数据流的相关性进行分类的。可能由入站或相关的状态更改而触发的事件包括:
- 连接被激活或连接失活
- 数据读取
- 用户事件
- 错误事件
- 打开或关闭到远程节点的连接
- 将数据写到或者冲刷到套接字
Channel,EventLoop和ChannelFuture
Channel是对socket的封装,EventLoop是控制流、多线程处理、并发的封装。ChannelFuture是对异步通知的封装。
Channel接口
基本的IO操作依赖于底层的socket,而Netty的Channel提供了许多的API避免了直接使用Socket的复杂性。
EventLoop接口
EventLoop定义了Netty的核心抽象,用于处理连接的什么周期中所发送的事件。
Channel、EventLoop、Thread以及EventLoopGroup的关系是怎样的?
- EventLoopGroup可以包含多个EventLoopGroup
- 一个EventLoop只能与一个Thread绑定
- 一个Channel只能注册于一个EventLoop
- 一个EventLoop可能被给配给多个Channel
ChannelFuture接口
由于Netty中的IO操作都是异步的,因此一个操作可能不会立即返回,所以我们需要一种用于在之后的某个节点确定其结果的方法,为此Netty提供了ChannelFuture接口,其中addListener方法注册一个ChannelFutureListenerr,以便在某个操作完成时得到通知。
Pipeline和ChannelPipeline
ChannelPipeline是一个Handler的集合,它负责处理和拦截inbound或者outbound的事件和操作。
入站事件和出站事件在一个双向链表中,入站事件会从链表头往后传递到最后入站的handler,出站事件会从链表尾往前传递到最前一个出站的handler。
Netty所使用的IO模型是什么?
Netty主要基于主从Reactors多线程模型。主从Reactors多线程模型有多个Reactor。
BossGroup和WorkerGroup是两组线程池,BoosGroup专门负责接收客户端连接,WorkerGroup专门负责网络读写操作。NIOEventloop表示一个不断循环执行处理任务的线程,每个NIOEventLoop都有一个selector,用于监听绑定在其上的socket网络通道。
- BossGroup线程维护Selector,只关注Accecpt
- 当接收到Accept事件就获取对应的SocketChannel,封装成NIOSocketChannel并注册到Worker线程(事件循环),并进行维护。
- 当Work而线程监听到selector中通道发送了自己该兴趣的事件后,就使用handler进行处理。