热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

20220507Core–8.DataBuffersandCodecs

前言文档地址JavaNIO提供了ByteBuffer,但是许多库在上面构建了自己的字节缓冲区API,特别是对于重用缓冲区或使用直接缓冲区对性能有益的网络操作。例如,Netty有By

前言

文档地址

Java NIO 提供了 ByteBuffer ,但是许多库在上面构建了自己的字节缓冲区 API,特别是对于重用缓冲区或使用直接缓冲区对性能有益的网络操作。例如,Netty 有 ByteBuf ,Undertow 使用 XNIO,Jetty 使用池化字节缓冲区,并带有要释放的回调,等等。

spring-core 模块提供了一组抽象来处理各种字节缓冲区 API,如下所示:



  • DataBufferFactory 抽象数据缓冲区的创建

  • DataBuffer 表示一个字节缓冲区,它可以被池化

  • DataBufferUtils 提供数据缓冲区的实用方法

  • 编解码器 Codecs 将流数据缓冲区流解码或编码为更高级别的对象


DataBufferFactory

DataBufferFactory 有两种方式创建数据缓冲区:



  • 分配一个新的数据缓冲区,可以选择预先指定容量,即使 DataBuffer 的实现可以按需增长和缩小,这也会更高效

  • 包装一个现有的 byte[]java.nio.ByteBuffer ,它用一个 DataBuffer 实现装饰给定的数据并且不涉及分配内存

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



  • org.springframework.core.io.buffer.DataBufferFactory


DataBuffer

DataBuffer 接口提供了类似 java.nio.ByteBuffer 的操作,但也带来了一些额外的好处,其中一些受到 Netty ByteBuf 的启发:



  • 以独立的位置读写,即不需要调用 flip() 在读取和写入之间交替

  • 容量按需扩展,类似于 java.lang.StringBuilder

  • 通过 PooledDataBuffer 来池化缓冲区和引用计数

  • 不同的缓冲区视图,java.nio.ByteBufferInputStreamOutputStream

  • 确定给定字节的前数索引或后数索引


PooledDataBuffer

正如 ByteBuffer 的 javadoc 中所述 ,字节缓冲区可以是直接的或非直接的。直接缓冲区可能驻留在 Java 堆之外,这就不需要对本地 I/O 操作进行复制。这使得直接缓冲区对于通过套接字接收和发送数据特别有用,但它们的创建和释放成本也更高,这导致了缓冲池的想法。

PooledDataBuffer 是有助于引用计数的 DataBuffer 扩展,这对于字节缓冲池至关重要。它是如何工作的?当分配 PooledDataBuffer 时,引用计数为 1。调用 retain() 增加计数,而调用 release() 减少它。只要计数大于 0,就保证不会释放缓冲区。当计数减少到 0 时,可以释放缓冲池,这在实践中可能意味着为缓冲区保留的内存返回到内存池。

请注意,在大多数情况下,最好使用 DataBufferUtils 里方便的方法,而不是直接操作 PooledDataBuffer ,该方法仅在 DataBufferPooledDataBuffer 的实例时,才将 releaseretain 应用于 DataBuffer


DataBufferUtils

DataBufferUtils 提供了许多实用方法来操作数据缓冲区:



  • 如果底层字节缓冲区 API 支持,则将数据缓冲区流加入可能具有零拷贝的单个缓冲区,例如通过复合缓冲区

  • 转型 InputStream 或 NIO ChannelFlux ,反之亦可,转型 PublisherOutputStream 或 NIO Channel

  • 如果缓冲区是 PooledDataBuffer 的实例,则释放或保留 DataBuffer 的方法

  • 跳过或从字节流中取出,直到达到特定的字节数


编解码器 Codecs

org.springframework.core.codec 包提供了以下策略接口:



  • Encoder :编码 Publisher 为数据缓冲区流

  • Decoder :解码 Publisher 为更高级别的对象流

spring-core 模块提供 byte[]ByteBufferDataBufferResourceString 编码器和解码器实现。spring-web 模块添加了 Jackson JSON、Jackson Smile、JAXB2、Protocol Buffers 等编码器和解码器。请参阅 WebFlux 部分中的编解码器。


使用 DataBuffer

使用数据缓冲区时,必须特别小心以确保缓冲区被释放,因为它们可能被池化。我们将使用编解码器来说明它是如何工作的,但这些概念应用得更广泛。让我们看看编解码器必须在内部做什么来管理数据缓冲区。

在创建更高级别的对象之前,Decoder 是最后一个读取输入数据缓冲区的,因此它必须按如下方式释放它们:



  1. 如果 Decoder 只是读取每个输入缓冲区并准备立即释放它,它可以通过 DataBufferUtils.release(dataBuffer)

  2. 如果 Decoder 是使用 FluxMono 操作,如 flatMapreduce 和其他该预取和高速缓存的数据项内部,或者是使用操作,如 filterskip 即省略数据项,或其他,然后 doOnDiscard(PooledDataBuffer.class, DataBufferUtils::release) 必须被添加到组合链以确保这些缓冲区在被丢弃之前被释放,这也可能导致错误或取消信号

  3. 如果 Decoder 以任何其他方式保留一个或多个数据缓冲区,则必须确保它们在完全读取时被释放,或者在读取和释放缓存数据缓冲区之前发生错误或取消信号的情况下释放它们

请注意,DataBufferUtils#join 提供了一种将数据缓冲区流聚合为单个数据缓冲区的安全有效的方法。同样 skipUntilByteCounttakeUntilByteCount 是解码器使用的额外安全方法。

Encoder 分配其他人必须读取(和释放)的数据缓冲区。所以 Encoder 没有什么可做的。但是,如果在用数据填充缓冲区时发生序列化错误,则 Encoder 必须小心释放数据缓冲区。例如:

DataBuffer buffer = factory.allocateBuffer();
boolean release = true;
try {
// serialize and populate buffer..
release = false;
}
finally {
if (release) {
DataBufferUtils.release(buffer);
}
}
return buffer;

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

请注意,在 Netty 上运行时,有用于排除缓冲区泄漏的调试选项 。



推荐阅读
  • Voicewo在线语音识别转换jQuery插件的特点和示例
    本文介绍了一款名为Voicewo的在线语音识别转换jQuery插件,该插件具有快速、架构、风格、扩展和兼容等特点,适合在互联网应用中使用。同时还提供了一个快速示例供开发人员参考。 ... [详细]
  • 如何实现织梦DedeCms全站伪静态
    本文介绍了如何通过修改织梦DedeCms源代码来实现全站伪静态,以提高管理和SEO效果。全站伪静态可以避免重复URL的问题,同时通过使用mod_rewrite伪静态模块和.htaccess正则表达式,可以更好地适应搜索引擎的需求。文章还提到了一些相关的技术和工具,如Ubuntu、qt编程、tomcat端口、爬虫、php request根目录等。 ... [详细]
  • 本文介绍了Python高级网络编程及TCP/IP协议簇的OSI七层模型。首先简单介绍了七层模型的各层及其封装解封装过程。然后讨论了程序开发中涉及到的网络通信内容,主要包括TCP协议、UDP协议和IPV4协议。最后还介绍了socket编程、聊天socket实现、远程执行命令、上传文件、socketserver及其源码分析等相关内容。 ... [详细]
  • 本文介绍了使用AJAX的POST请求实现数据修改功能的方法。通过ajax-post技术,可以实现在输入某个id后,通过ajax技术调用post.jsp修改具有该id记录的姓名的值。文章还提到了AJAX的概念和作用,以及使用async参数和open()方法的注意事项。同时强调了不推荐使用async=false的情况,并解释了JavaScript等待服务器响应的机制。 ... [详细]
  • 本文介绍了C#中生成随机数的三种方法,并分析了其中存在的问题。首先介绍了使用Random类生成随机数的默认方法,但在高并发情况下可能会出现重复的情况。接着通过循环生成了一系列随机数,进一步突显了这个问题。文章指出,随机数生成在任何编程语言中都是必备的功能,但Random类生成的随机数并不可靠。最后,提出了需要寻找其他可靠的随机数生成方法的建议。 ... [详细]
  • 如何使用Java获取服务器硬件信息和磁盘负载率
    本文介绍了使用Java编程语言获取服务器硬件信息和磁盘负载率的方法。首先在远程服务器上搭建一个支持服务端语言的HTTP服务,并获取服务器的磁盘信息,并将结果输出。然后在本地使用JS编写一个AJAX脚本,远程请求服务端的程序,得到结果并展示给用户。其中还介绍了如何提取硬盘序列号的方法。 ... [详细]
  • 如何用UE4制作2D游戏文档——计算篇
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了如何用UE4制作2D游戏文档——计算篇相关的知识,希望对你有一定的参考价值。 ... [详细]
  • 本文介绍了在开发Android新闻App时,搭建本地服务器的步骤。通过使用XAMPP软件,可以一键式搭建起开发环境,包括Apache、MySQL、PHP、PERL。在本地服务器上新建数据库和表,并设置相应的属性。最后,给出了创建new表的SQL语句。这个教程适合初学者参考。 ... [详细]
  • 本文介绍了使用Java实现大数乘法的分治算法,包括输入数据的处理、普通大数乘法的结果和Karatsuba大数乘法的结果。通过改变long类型可以适应不同范围的大数乘法计算。 ... [详细]
  • Java序列化对象传给PHP的方法及原理解析
    本文介绍了Java序列化对象传给PHP的方法及原理,包括Java对象传递的方式、序列化的方式、PHP中的序列化用法介绍、Java是否能反序列化PHP的数据、Java序列化的原理以及解决Java序列化中的问题。同时还解释了序列化的概念和作用,以及代码执行序列化所需要的权限。最后指出,序列化会将对象实例的所有字段都进行序列化,使得数据能够被表示为实例的序列化数据,但只有能够解释该格式的代码才能够确定数据的内容。 ... [详细]
  • 开发笔记:加密&json&StringIO模块&BytesIO模块
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了加密&json&StringIO模块&BytesIO模块相关的知识,希望对你有一定的参考价值。一、加密加密 ... [详细]
  • Android中高级面试必知必会,积累总结
    本文介绍了Android中高级面试的必知必会内容,并总结了相关经验。文章指出,如今的Android市场对开发人员的要求更高,需要更专业的人才。同时,文章还给出了针对Android岗位的职责和要求,并提供了简历突出的建议。 ... [详细]
  • 本文介绍了如何使用php限制数据库插入的条数并显示每次插入数据库之间的数据数目,以及避免重复提交的方法。同时还介绍了如何限制某一个数据库用户的并发连接数,以及设置数据库的连接数和连接超时时间的方法。最后提供了一些关于浏览器在线用户数和数据库连接数量比例的参考值。 ... [详细]
  • Metasploit攻击渗透实践
    本文介绍了Metasploit攻击渗透实践的内容和要求,包括主动攻击、针对浏览器和客户端的攻击,以及成功应用辅助模块的实践过程。其中涉及使用Hydra在不知道密码的情况下攻击metsploit2靶机获取密码,以及攻击浏览器中的tomcat服务的具体步骤。同时还讲解了爆破密码的方法和设置攻击目标主机的相关参数。 ... [详细]
  • 本文介绍了Oracle数据库中tnsnames.ora文件的作用和配置方法。tnsnames.ora文件在数据库启动过程中会被读取,用于解析LOCAL_LISTENER,并且与侦听无关。文章还提供了配置LOCAL_LISTENER和1522端口的示例,并展示了listener.ora文件的内容。 ... [详细]
author-avatar
喝西北风的东北风_711
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有