本文主要是介绍[netty核心类]--缓冲区ByteBuf,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
本文主要包括以下内容:
1)ByteBuf的三种类型:heapBuffer(堆缓冲区)、directBuffer(直接缓冲区)以及Composite Buffer(复合缓冲区)。2)ByteBuf的工作原理。
3)ByteBuf与JDK中ByteBuffer的区别以及对比
4)ByteBuf的引用计数器实现类AbstractReferenceCountedByteBuf分析。
5)UnpooledHeapByteBuf 基于堆内存缓冲器的源码分析
6)PooledDirectByteBuf 源码分析
1. netty中ByteBuf的优势
缓冲区是不同的通道之间传递数据的中介,JDK中的ByteBuffer操作复杂,而且没有经过优化,所以在netty中实现了一个更加强大的缓冲区 ByteBuf 用于表示字节序列。ByteBuf在netty中是通过Channel传输数据的,新的设计解决了JDK中ByteBuffer中的一些问题。
netty中ByteBuf的缓冲区的优势:
(1)可以自定义缓冲区的类型;
(2)通过内置的复合缓冲类型实现零拷贝;
(3)不需要调用flip()函数切换读/写模式
(4)读取和写入的索引分开了,不像JDK中使用一个索引
(5)引用计数(referenceCounting的实现原理?)
(6) Pooling池
2.netty中的ByteBuf的类型:
JDK中的Buffer的类型 有heapBuffer和directBuffer两种类型,但是在netty中除了heap和direct类型外,还有composite Buffer(复合缓冲区类型)。
(1)Heap Buffer 堆缓冲区
这是最常用的类型,ByteBuf将数据存储在JVM的堆空间,通过将数据存储在数组中实现的。
1)堆缓冲的优点是:由于数据存储在JVM的堆中可以快速创建和快速释放,并且提供了数组的直接快速访问的方法。
2)堆缓冲缺点是:每次读写数据都要先将数据拷贝到直接缓冲区再进行传递。
(2)Direct Buffer 直接缓冲区
Direct Buffer在堆之外直接分配内存,直接缓冲区不会占用堆的容量。
(1)Direct Buffer的优点是:在使用Socket传递数据时性能很好,由于数据直接在内存中,不存在从JVM拷贝数据到直接缓冲区的过程,性能好。
(2)缺点是:因为Direct Buffer是直接在内存中,所以分配内存空间和释放内存比堆缓冲区更复杂和慢。
虽然netty的Direct Buffer有这个缺点,但是netty通过内存池来解决这个问题。直接缓冲池不支持数组访问数据,但可以通过间接的方式访问数据数组:
ByteBuf directBuf = Unpooled.directBuffer(16);
if(!directBuf.hasArray()){ int len = directBuf.readableBytes(); byte[] arr = new byte[len]; directBuf.getBytes(0, arr);
}
但是上面的操作太过复杂,所以在使用时,建议一般是用heap buffer。
不过对于一些IO通信线程中读写缓冲时建议使用DirectByteBuffer,因为这涉及到大量的IO数据读写。对于后端的业务消息的编解码模块使用HeapByteBuffer。
(3)Composite Buffer 复合缓冲区
这个是netty特有的缓冲类型。复合缓冲区就类似于一个ByteBuf的组合视图,在这个视图里面我们可以创建不同的ByteBuf(可以是不同类型的)。 这样,复合缓冲区就类似于一个列表,我们可以动态的往里面添加和删除其中的ByteBuf,JDK里面的ByteBuffer就没有这样的功能。
Netty提供了Composite ByteBuf来处理复合缓冲区。例如:一条消息由Header和Body组成,将header和body组装成一条消息发送出去。下图显示了Composite ByteBuf组成header和body:
如果使用的是JDK的ByteBuffer就不能简单的实现,只能通过创建数组或则新的ByteBuffer,再将里面的内容复制到新的ByteBuffer中,下面给出了一个CompositeByteBuf的使用示例:
//组合缓冲区
CompositeByteBuf compBuf = Unpooled.compositeBuffer();
//堆缓冲区
ByteBuf heapBuf = Unpooled.buffer(8);
//直接缓冲区
ByteBuf directBuf = Unpooled.directBuffer(16);
//添加ByteBuf到CompositeByteBuf
compBuf.addComponents(heapBuf, directBuf);
//删除第一个ByteBuf
compBuf.removeComponent(0);
Iterator<ByteBuf> iter = compBuf.iterator();
while(iter.hasNext()){ System.out.println(iter.next().toString());
} //使用数组访问数据
if(!compBuf.hasArray()){ int len = compBuf.readableBytes(); byte[] arr = new byte[len]; compBuf.getBytes(0, arr);
}
这篇关于[netty核心类]--缓冲区ByteBuf的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!