chapter15 ByteBuf和相关辅助类

20 篇文章 0 订阅
12 篇文章 0 订阅

chapter15 ByteBuf和相关辅助类

1、ByteBuf诞生背景:

  • NIO中,除了Boolean外,其他基础类型都有自己的缓冲区实现,但主要使用的是ByteBuffer,但其存在以下主要缺点:
    1. ByteBuffer长度固定,编码大POJO时,容易发生越界异常
    2. ByteBuffer只有一个标识位置的指针position,读写的时候需要手工调用flip()和rewind()等,使用需要谨慎处理
    3. ByteBuffer的API功能有限,一些高级和实用的特性它不支持
  • 因此Netty提供了自己的ByteBuffer实现——ByteBuf。

2、ByteBuf的工作原理

  • 基本功能:
    1. 7种java基础类型、byte数组、ByteBuffer(ByteBuf)等的读写;
    2. 缓冲区自身的copy和slice等;
    3. 设置网络字节序;
    4. 构造缓冲区实例;
    5. 操作位置指针等方法;
  • Netty实现策略:
    1. 参考ByteBuffer的实现,增加额外的功能,解决原ByteBuffer的缺点;
    2. 聚合ByteBuffer,通过facade模式对其包装,可以减少自身代码量,降低实现成本。
  • ByteBuffer中有position、limit、capacity,ByteBuf定义了readerIndex、writerIndex、capacity,将读写分开简化了操作。

  • ByteBuf动态扩展的实现:

    • 对write操作进行了封装,由write操作负责进行剩余可用空间的校验,如果缓冲不够,ByteBuf自动进行扩展,使用者不需要关系校验和扩展的逻辑,只要不超过设置的最大缓冲区容量即可

3、ByteBuf功能介绍

  1. 顺序读操作(read)
    • 类似于ByteBuffer的get操作。
  2. 顺序写操作(write)
    • 类似于ByteBuffer的put操作。
  3. readerIndex和writerIndex
    • 0 <= readerIndex <= writerIndex <= capacity
    • 0到readerIndex为已经读取过的缓冲区,可以调用discardReadBytes操作来重用这部分空间,节约内存,防止ByteBuf的动态扩张,非常适合用于解决TCP沾包问题。
  4. Discardable bytes
    • 降低性能换取内存操作,因为discardReadBytes会发生子节数组的内存复制,所以,频繁调用会降低性能。
  5. Readable bytes和Writable bytes
    • 当读取的子节长度大于可读字节数,则会抛出IndexOutOfBoundsException。同理写入的超过可写入的也会抛出该异常。
  6. Clear操作
    • 还原为初始分配值。
  7. Mark和Rest
    • markReaderIndex,将当前的readerIndex备份到markedReaderIndex中
    • resetReaderIndex,将当前的readerIndex设置为markReaderIndex
    • write同理。
  8. 查找操作
  9. Derived buffers
    • 创建某个ByteBuf的视图或者复制ByteBuf。
    • duplicate、copy、copy(int index,int length)、slice、slice(int index,int length)
  10. 转成标准的ByteBuffer
    • nioByteBuffer()、nioByteBuffer(int index,int length)创建的ByteBuffer都无法感知ByteBuf的动态扩展。
  11. 随机读写(set和get)
    • set操作不会动态扩展缓冲区。

4、ByteBuf源码分析

  • 从内存角度,分为两类:
    1. 堆内存 (HeapByteBuf)
      • 特点是分配与回收快,可以被JVM自动回收;缺点就是进行Socket的IO读写,需要额外做一次内存复制,将堆内存复制到对应的Channel中,会降低性能。
    2. 直接内存(DirectByteBuf)
      • 在堆外进行内存分配,分配和回收会慢一些,但是写入Channel中,少了一次内存复制,速度比堆内存快。
  • 最佳实践:在IO通信线程的读写缓冲区采用DirectByteBuf,后端业务消息的编码解码模块使用HeapByteBuf。
  • 从内存回收角度:
    1. 基于对象池ByteBuf
      • 可以重用ByteBuf,提升内存利用率,降低高负载下导致的频繁GC,适合高负载,高并发。
    2. 普通ByteBuf
      • AbstractByteBuf
      • AbstractReferenceCountedByteBuf
      • 对引用进行计数,采用CAS
      • UnpooleedHeapByteBuf
      • 基于堆内存进行内存分配的字节缓冲区,没有基于对象池实现
      • PooledByteBuf
        1. PoolArena
          • Arena本身是指一块区域,在内存管理中,Memory Arena是指内存中的一大块连续的区域(提前申请的一大块内存),PoolArena就是Netty的内存池实现。
          • 由多个Chunk组成、每个Chunk由一个或者多个Page组成,Page被构建成一颗二叉树。
        2. PoolChunk
        3. PoolSubpage
        4. 内存回收策略
          • Chunk和Page都通过状态位来标识内存是否可用。Chunk通过标识二叉树上的节点实现,Page通过维护块的使用状态来实现。
        5. PooledDirectByteBuf
          • 基于内存池实现,与UnPooleedDirectByteBuf唯一不同就是缓冲区的分配和销毁策略不同。

5、ByteBuf相关辅助类

  1. ByteBufHolder
    • ByteBuf的容器,为了满足定制化需求,使用者继承ByteBufHolder接口后可以按需封装自己的实现。
  2. ByteBufAllocator
    • 字节缓冲区分配器,按照Netty的缓冲区实现不同,分为两种:基于内存池的字节缓冲区分配器和普通的字节缓冲区分配器。
  3. CompositeByteBuf
    • 允许将多个ByteBuf的实例组装到一起,形成一个统一的视图。如消息体和消息头
  4. ByteBufUtil
    • 提供了实用的工具类,如encodeString、decodeString、转换16进制的hexDump等。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值