回顾一下之前使用Netty 进行开发的一个百万物联网设备网关,其中我觉得里面最好用的就是Netty 的ByteBuf,从源码整体的设计回顾一下
在Netty中他的ByteBuf 一共有 有4 种类型吧
从他所在的内存区域来划分:
ReferenceCounted 用于引用计数,就是专门针对pool 的
ByteBuf 是一个操作的抽象,定义了read write 的一些一些方法
AbstractReferenceCountedByteBuf 就是对上面一些封装,资源的回收的
底层就有 PooledByteBuf UnpooledHeapByteBuf UnpooledDirectByteBuf
ByteBufAllocator 是一个专门用于allocat 各种buffer,可以理解为一个抽象工厂
对于具体的抽象工厂他有UnpooledByteBufAllocator PooledByteBufAllocator 的实现
其中PooledByteBufAllocator 里面含有一个PoolArena ,他是每一个线程都有自己独立的PoolArena ,这样的设计也降低了线程资源的并发需要一些同步带来的复杂设计,已经性能降低
PoolArena 里面包含了PooledByteBuf ,而到他们分别的子类PooledHeapByteBuf PooledDirectByteBuf 和 HeapArena DirectArena 具体去实现create 操作
这里也是用了 桥接的设计模式在里面 PooledByteBuf PoolArena 进行一个连接
PooledByteBufAllocator 关联了PoolArena 从而 将factory 和具体的生成的product 进行一个结合
一般当我们数据到来了,io 线程指向decode里面可以是使用的是Unpooled.headBuffer() ,因为我们这个需要在业务里面进行不断的对他进行操作
如果是进行io 的话,使用Direct buf 这样减少io 的copy
这仅仅以Unpooled.headBuffer 例子
它的里面其实一个 byte[] array; 数组用于存放真正的数据
当我们对他进行具体的read 和write 的时候其实是操作的是readIndex writeIndex
基类 AbstractByteBuf
public abstract class AbstractByteBuf extends ByteBuf { int readerIndex; int writerIndex; private int markedReaderIndex; private int markedWriterIndex; private int maxCapacity; }
看一下他的read short
@Override public short readShort() { checkReadableBytes0(2); short v = _getShort(readerIndex); readerIndex += 2; return v; }
因为short 占用2 个字节,所以他会 readIndex+=2,读操作就是对readIndex 进行
同理写是对writeIndex
public ByteBuf writeShort(int value) { ensureWritable0(2); _setShort(writerIndex, value); writerIndex += 2; return this; }
如下图
当read index 超过 wriete index 会有一个 数组越界的异常
capacity 是当前的容量,这个容量是扩容的,最大容量是int 的最大值