b Spring之Databuffer & Codecs--为IO准备的buffer&编解码

–> go to 总目录

文章目录

  • 8 Data Buffers and Codecs
    • 8.1 DataBufferFactory
    • 8.2. DataBuffer
    • 8.3. PooledDataBuffer
    • 8.4. DataBufferUtils
    • 8.5. Codecs
    • 8.6 使用 Using DataBuffer

8 Data Buffers and Codecs

java NIO提供了ByteBuffer但是很多库是基于byte bufferAPI的在上层封装,特别是buffer的重用,和直接使用buffer。例如netty有自己的ByteBuf借口。jetty有池化的byte buffer(带一个回调去释放)。Spring-core提供了一系列抽象的byte buffer APIs。

  • DataBufferFactory databuffer的抽象创造
  • DataBuffer 代表 byte buffer可能被池化
  • DataBufferUtils 提供data buffer工具API
  • Codecs 高级对象的decode和encode。

8.1 DataBufferFactory

DataBufferFactory创建data buffers使用以下两种方式。

  1. 分配一个新的数据缓冲区,可以选择预先指定容量(如果已知),即使DataBuffer的实现可以按需增长和缩小,该容量也会更有效。
  2. 包装一个现有的byte[]或java.nio.ByteBuffer,它们用DataBuffer实现修饰给定的数据,并且不涉及allocation。

请注意,WebFlux应用程序不会直接创建DataBufferFactory,而是通过客户端的ServerHttpResponse或ClientHttpRequest访问它。工厂的类型取决于基础客户端或服务器,例如NettyDataBufferFactory用于Reactor Netty,DefaultDataBufferFactory用于其他。

8.2. DataBuffer

DataBuffer接口提供与java.nio.ByteBuffer类似的操作,但还带来了一些其他好处,其中一些是受Netty ByteBuf启发的。以下是部分好处清单:
b Spring之Databuffer & Codecs--为IO准备的buffer&编解码_第1张图片

8.3. PooledDataBuffer

如Javadoc中ByteBuffer所述,字节缓冲区可以是直接的也可以是非直接的。直接缓冲区可以驻留在Java堆之外,从而无需复制本机I / O操作。这使得直接缓冲区对于通过套接字接收和发送数据特别有用,但是它们的创建和释放也更昂贵,这导致了缓冲池的想法。 PooledDataBuffer是DataBuffer的扩展,可帮助进行引用计数,这对于字节缓冲区池至关重要。它是如何工作的?分配PooledDataBuffer时,引用计数为1。调用keep()会增加计数,而调用release()会减少计数。只要计数大于0,就保证不会释放缓冲区。当计数减少到0时,可以释放池中的缓冲区,这实际上意味着将为缓冲区保留的内存返回到内存池。 请注意,与其直接在PooledDataBuffer上进行操作,不如在大多数情况下,最好使用DataBufferUtils中的便捷方法,仅当它是PooledDataBuffer的实例时才将释放或保留应用于DataBuffer。

8.4. DataBufferUtils

DataBufferUtils提供了许多实用程序方法来对数据缓冲区进行操作:

  • 将数据缓冲区流连接到单个缓冲区中,可能具有零个副本,例如通过复合缓冲区(如果基础字节缓冲区API支持的话)。
  • 将InputStream或NIO通道转换为Flux ,反之亦然,将Publisher 转换为OutputStream或NIO通道
  • 如果缓冲区是PooledDataBuffer的实例,则释放或保留DataBuffer的方法。
  • 从字节流中跳过或获取,直到特定的字节数为止。

8.5. Codecs

org.springframework.core.codec包提供以下策略接口:
b Spring之Databuffer & Codecs--为IO准备的buffer&编解码_第2张图片
spring-core模块提供byte [],ByteBuffer,DataBuffer,Resource和String编码器和解码器实现。 spring-web模块添加了Jackson JSON,Jackson Smile,JAXB2,Protocol Buffers和其他编码器和解码器。请参阅WebFlux部分中的编解码器。

8.6 使用 Using DataBuffer

使用数据缓冲区时,必须特别小心以确保释放缓冲区,因为它们可能会被合并。我们将使用编解码器来说明其工作原理,但是这些概念会更普遍地应用。让我们看看编解码器必须在内部执行哪些操作来管理数据缓冲区。
在创建更高级别的对象之前,解码器是最后一个读取输入数据缓冲区的对象,因此,它必须按以下方式释放它们:

  • 1 如果解码器只是读取每个输入缓冲区并准备立即释放它,则可以通过DataBufferUtils.release(dataBuffer)这样做。
  • 2 如果Decoder使用的是Flux或Mono运算符(例如flatMap,reduce和其他在内部预取和缓存数据项的运算符),或者使用的运算符(例如filter,skip和其他省略项的运算符),则doOnDiscard(PooledDataBuffer.class,DataBufferUtils必须将::: release)添加到组合链中,以确保在丢弃此类缓冲区之前将其释放,这也可能是错误或取消信号的结果
  • 3 如果解码器以任何其他方式保留一个或多个数据缓冲区,则它必须确保在完全读取时释放它们,或者在读取和释放缓存的数据缓冲区之前发生错误或取消信号的情况下。

请注意,DataBufferUtils#join提供了一种安全有效的方法来将数据缓冲区流聚合到单个数据缓冲区中。同样,skipUntilByteCount和takeUntilByteCount是供解码器使用的其他安全方法。 编码器分配其他人必须读取(和释放)的数据缓冲区。因此,编码器无事可做。但是,如果在使用数据填充缓冲区时发生序列化错误,则编码器必须小心释放数据缓冲区。例如:

编码器的使用者负责释放其接收的数据缓冲区。在WebFlux应用程序中,编码器的输出用于写入HTTP服务器响应或客户端HTTP请求,在这种情况下,释放数据缓冲区是代码写入服务器响应或客户端的责任。请求。

你可能感兴趣的:(b Spring之Databuffer & Codecs--为IO准备的buffer&编解码)