netty概述
1) netty是基于Java NIO的网络应用框架,client-server框架。
2)netty是高性能、异步事件驱动的NIO框架,它提供了对TCP、UDP和文件传输的支持,作为异步NIO框架,netty所有的IO操作都是异步非阻塞的,通过future-listener机制,用户可以方便地主动获取,或通过通知机制获得IO的操作结果。
netty的优势
并发高
netty是基于NIO(non-blocking I/O, 非阻塞IO)的网络通信框架,相比传统的BIO(Blocking I/O, 阻塞IO),netty并发性大大提高。
具体不同如下图:
-
BIO:
-
NIO:
从上图可以看出,对于服务端的一个线程,NIO能处理的连接数比BIO要多得多。那么,为什么NIO单线程可以处理不只一个连接呢?答案是:因为selector。
当客户端与服务端建立连接后,服务端有两件事要做:
1)接收客户端发送的全部数据
2)服务端处理完请求后,返回response给客户端。
NIO与BIO的关键区别在于第一步:
1)对于BIO,等待客户端发送数据的过程是阻塞的,这样就造成一个线程只能处理一个请求,而机器能支持的最大线程数是有限的,这就是BIO不支持高并发的原因。
2)在NIO中,当一个socket建立完成后,服务端的Thread并不会阻塞地等待这个socket的请求数据,而是将请求交给selector, 由selector不断去遍历所有的socket,一旦发现有一个socket有请求数据,他会通知该Thread,然后由该Thread处理完数据,再返回处理结果给客户端,这个过程是阻塞的。这样就可以让一个线程处理多个请求了。
传输快
netty传输快,主要是因为“零拷贝”。
Java的数据主要存储在堆内存。从IO读取到堆内存,中间需要经过socket缓冲区,然后再到堆内存,这样要copy两次。
netty采用了零拷贝。当netty需要接收数据时,会在堆内存之外开辟一块内存,数据直接从IO读到了这块内存中。netty中通过ByteBuf可直接对这些数据进行操作,从而加快了传输速度。
封装好
netty的实现NIO通信代码简洁。
netty的重要概念
1. Channel
channel可理解为数据传输流。
1)Channel: 表示一个连接,可以理解为客户端每一个请求,就是一个Channel。
2)ChannelHandler:用于处理业务请求。
3)ChannelHandlerContext:用于传输业务数据。
4)ChannelPipeline:用于保存处理过程中需要用到的ChannelHandler和ChannelHandlerContext。
ByteBuf
ByteBuf是一个存储字节的容器,最大特点是使用方便。它有自己的读索引和写索引,方便对整段自己缓存进行读写,也支持get/set,方便你对其中每一个自己进行读写。ByteBuf的数据结构如下:
ByteBuf是三种使用模式:
1)Heap Buffer:堆缓冲区
堆缓冲区是ByteBuf最常用的模式,它将数据存储在堆空间。
2)Direct Buffer:直接缓冲区
直接缓冲区也是ByteBuf最常用的使用模式,它的内存分配都不在堆中。JDK1.4开始引入的NIO的ByteBuffer类允许JVM通过本地方法调用分配内存。使用直接缓冲区的好处:
- 避免了堆内存的内存copy步骤,提高了IO处理速度。直接缓冲区的内容可以驻留在GC扫描的堆区以外。
- DirectBuffer使用堆外内存,GC对此“无能为力”,这样就规避了在高并发下频繁GC时stop the world的影响。
3)Composite Buffer:复合缓冲区
复合缓冲区相当于多个不同的ByteBuf视图,是netty提供的。JDK没有这样的功能。
Codec
Codec是netty中的编码/解码器,通过Codec你能完成字节与对象的转换,即序列化、反序列化。从而实现自定义协议的目的。
在netty里,Codec最著名的就是HttpRequestDecoder和HttpResponseEncoder了。