netty 案例,netty4.1 源码分析篇四《ByteBuf 的数据结构在使用方式中的剖析》
前言介绍
在Netty中ByteBuf是一个非常重要的类,它可以以高效易用的数据结构方式来满足网络通信过程中处理数据包内字节码序列的移动。
数据结构
那么这种数据结构之所以能高效的处理数据传输处理并解决半包粘包,主要得益于ByteBuf中有两个不同的索引;读索引(readIndex)、写索引(writerIndex)。
读索引:当我们从ByteBuf读取数据时,readerIndex指针位置也会指向到读取字节位置
写索引:当我们向ByteBuf写入数据时,writerIndex指针位置也会指向到写入字节位置
discardable bytes:当从ByteBuf读取一部分数据后,这部分数据就属于discardable,他们是可以被废弃的。
readable bytes:剩余可以继续读取的内容区域,就像一个长条的鸡蛋卡槽,一边放一边拿。从已经拿完到剩余的鸡蛋位置属于可拿区域。
writable bytes:同上一样,这一部分就是可以继续放置鸡蛋的位置。
功能案例
内存模型
1、堆内内存(JVM堆空间内)
最常用的ByteBuf模式是将数据存储在JVM的堆空间中。它能在没有使用池化的情况下提供快速的分配和释放。
2、堆外内存(本机直接内存)
JDK允许JVM实现通过本地调用来分配内存。主要是为了避免每次调用本地I/O操作之前(或者之后)将缓冲区的内容复制到一个中间缓冲区(或者从中间缓冲区把内容复制到缓冲区)。
3、复合缓冲区(以上2种缓冲区多个混合)
常用类:CompositeByteBuf,它为多个ByteBuf提供一个聚合视图,将多个缓冲区表示为单个合并缓冲区的虚拟表示。
比如:HTTP协议:头部和主体这两部分由应用程序的不同模块产生。这个时候把这两部分合并的话,选择CompositeByteBuf是比较好的。
源码解读
>ByteBuf实现了ReferenceCounted与Comparable两个接口
>创建一个指定容量大小堆缓冲区,并按需扩充容量{与list集和很像},指针位置都是从0开始
>跟进代码的创建过程会发现,UnpooledHeapByteBuf.UnpooledHeapByteBuf用来创建非池化堆Buf
内容总结
ByteBuf提供了两个指针;读、写,分别用来标记“可读”、“可写”、“可丢弃”的字节
通过调用write*方法写入数据后,写指针将会向后移动
通过调用read*方法读取数据后,读指针将会向后移动
写入数据或读取数据时会检查是否有足够多的空间可以写入和是否有数据可以读取
写入数据之前会进行容量检查,当剩余可写的容量小于需要写入的容量时,需要执行扩容操作
clear等修改读写指针的方法,只会更改读写指针的值,并不会影响ByteBuf中已有的内容
------------
版权声明: 本文为 InfoQ 作者【小傅哥】的原创文章。
原文链接:【http://xie.infoq.cn/article/4545df9e261b2799784b6d1a9】。文章转载请联系作者。
评论