Netty in Action (十二) 第五章节 第一部分 简介ByteBuf

第五章 ByteBuf(分四部分翻译)

本章节包括:

1)ByteBuf------Netty的数据容器

2)API介绍

3)使用案例

4)内存分配

我们之前提到过很多次,网络传输数据的最基本的数据单元是byte,Java的NIO提供了ByteBuffer作为字节的容器,但是这个类的使用有些过于复杂和麻烦

Netty对ByteBuffer提供了一个可选方案ByteBuf,一个很好的解决方案,解决了JDK原生的ByteBuffer的API使用不易的问题,同时ByteBuf为应用程序开发者提供了一系列的更好用的API

在这个章节中,我们以与JDK的ByteBuffer对比的方式介绍ByteBuf的最主要的功能和灵活性,这也会让你加深Netty对数据处理整体思路的理解,让你为第六章节讲解ChannelPipeline和ChannelHandler做好准备

5.1 The ByteBuf API

Netty对数据的处理的API通过两个组件去暴露-------抽象类ByteBuf和ByteBufHolder

以下是ByteBuf的API的一些优点:

1)对于用户自定义的buffer类型是可扩展的

2)对于透明的zero-copy可以通过内置的符合buffer类型可以达到你的要求

3) ByteBuf的容量如JDK的StringBuffer一样可以按照需要扩展

4)切换读写模式不需要调用ByteBuffer的flip方法

5)读和写有自己的独有索引下标

6)支持方法链式调用

7)支持引用计数

8)支持pooling

还有一些其他的相关类可以被用来管理ByteBuf实例的分配,这些类可以被用来提供对容器里的数据各种各样的操作,我们将在讲解ByteBuf和ByteBufHolder的时候探索这些特性

5.2 Class ByteBuf—Netty’s data container

因为所有的网络传输都需要byte的序列化后的移动,所以一个高效且易用的传输数据结构模型对于网络传输来说就是必不可少了,Netty的ByteBuf的实现就满足且超过了这些要求,让我们从看Netty如何使用索引来简单地获取ByteBuf中的数据来开始我们的学习吧~

5.2.1 How it works

ByteBuf有两个索引,一个用来读一个用来写,当你从ByteBuf中读取数据的时候,ByteBuf的readerIndex会随着被读取的字节的数量的增加而递增,与读相同,当你写一个字节的数据,那么ByteBuf的writerIndex也会递增加一,图5.1向你展示了一个空的ByteBuf的结构布局

为了理解这两个索引之间的关系,你看可以思考一下出现下面情形的时候会发生什么:当你读取数据的时候,读的readerIndex索引下标已经与写的writerIndex的下标值一样了,可以这么理解,在这个时候,你已经达到了可读的最大下标了,如果你接着尝试去读取更多的内容的时候,你会触发一个IndexOutOfBoundException的异常,与你操作数据最后一个元素的下一个元素一样

ByteBuf中以“read”和“write"名字为开头的方法都会相应的增加其对应的索引下标值,然而名字以”set“和”get“开头的方法则不会改变下标值,后者的方法需要将一个下标值以参数的方式传递给方法操作相关的数据

ByteBuf的最大容量是可以限制的(默认值是Integer.MAX_VALUE),如果尝试增加写的索引下标超过这个最大值的话,会触发一个异常

5.2.2 ByteBuf
usage patterns

使用Netty的时候,你会碰到一些常用的构建于ByteBuf的常用的普通的使用模式,通过我们对它的分析,我们会把图5.1展示的模型牢记心中,一个字节数组,这个数组带有两个不同的索引来分别控制读和写

HEAP
BUFFERS

使用ByteBuf模式存储数据的最最常用的方式是将数据存储在JVM的堆空间,被称之为“backing array”,这种方式提供了快速分配和在堆中对象无用的时候取消分配的功能,代码清单5.1向你展示了这个方法,这个方法同样适用于处理传统数据的情形

注意当使用hasArray()方法的时候来尝试获取backing array的时候,也能回返回false,可能会触发一个UnsupportedOperationException的异常,这个模式与JDK的ByteBuffer的用法一样

DIRECT BUFFERS

Direct buffer是另一个ByteBuf模式,我们希望为创建的对象分配的内存都来自于堆,这个模式可以使我们不需要必须使用JDK1.4
NIO中ByteBuffer类来允许JVM来通过原生的方法调用分配内存,这样做的目的是禁止在每一个IO操作上复制一个buffer的内容到中间状态的buffer上

ByteBuffer的Java的文档陈述的很清楚“直接缓冲区处于正常垃圾回收区之外”,这就解释了为什么直接缓冲区对于网络数据传输是理想的,如果你的数据是被装载在堆分配的buffer中的时候,在你将其通过socket发送之前JVM会将你的buffer复制到堆外的direct
buffer中

这个最主要的缺点就是direct buffer它们有时候比堆内buffer分配和释放内存浪费更多的性能,如果你写过一些过去的旧式代码你也许会遇到这个缺点,因为数据并不在堆区,你可能需要做个复制,如下面代码清单所示:

很清楚,这比使用backing buffer多了一些操作,所以如果你能提前知道在这个direct buffer中的数据可以被作为一个array获取到的话,你可能会选择堆内存

COMPOSITE BUFFERS

第三种也是终极的模式就是composite buffer,这也是前两种模式的一种聚合模式,在这里你可以按照你的需要增加或者删除ByteBuf实例,这种特性在JDK的ByteBuffer实现中完全缺失

Netty用ByteBuf的子类CompositeByteBuf提供了这种多元buffer(可做单个buffer亦可作为合并buffer)实际代表

注意ByteBuf在CompositeByteBuf的实例可能会包括直接和非直接分配两种模式,如果它只是一个实例,那么调用CompositeByteBuf的hasArray()方法,会返回对应的那部分组件,如果没有则会返回false

为了说明,我们可以思考有这么一个对象,它由两部分组成,header和body,将由Http协议传输,这两个部分是由不同的应用模块产生的然后将其组装成信息然后发送出去,这个应用还有这样的需求:在多个消息中,不同的header可以对应同一个body,如果有这样的需求发生,那么你需要为每一个消息创建一个header

因为我们不需要为每一个消息分配两个部分的内存(body部分不需要多次分配),那么CompositeByteBuf这个对象很适合使用,通过使用CompositeByteBuf暴露的API,可以消除很多不必要的复制,图5.2展示了结果信息的结构

下面的代码清单向你展示了如果使用JDK的原生API是如何实现这个功能的:创建ByteBuffer的数组然后用数组存放信息的组件,然后创建第三个复制所有的数据到第三个ByteBuffer中

分配和赋值的操作,包括对数据管理的需要,使这个版本的实现看起来有点尴尬,且有些低效,下面的代码清单向你展示了使用CompositeByteBuf实现的版本

CompositeByteBuf中可能不允许直接获取backing array,所以想要像direct buffer模式一样获取数据,如下面的代码清单所示:

注意Netty使用了CompositeByteBuf优化了socket的I/O,消除了在JDK的buffer实现中出现的内存和性能损耗的,这个优化是在Netty核心内部代码实现的,并没有暴露出来,但是你必须意识到它带给你的好处

COMPOSITEBYTEBUF
API
CompositeByteBuf除了从ByteBuf中继承的方法之外,它还额外提供了一大堆额外的方法,详细可以参考java的文档

时间: 2024-08-05 13:11:50

Netty in Action (十二) 第五章节 第一部分 简介ByteBuf的相关文章

Netty in Action (二十三) 第十二章节 WebSocket

第三部分:网络协议 WebSocket是一个先进的网络协议,被开发用来用来提高网络的性能和web应用的响应率,我们将介绍Netty对WebSocket这两个特性的支持,同时我们也会举一个简单的实例来说明讲解这两个WebSocket的特性 在第十二章节中,你将学会如何使用WebSocket实现数据双向传输的功能,我们会写一个聊天室的方式讲解这个数据双向传输的问题,我们这个聊天室的实例是这样的:多个浏览器客户端可是实时的相互通信,你也会学会如何将普通的HTTP协议切换升级成WebSocket协议,当

Netty in Action (二十一) 第十一章节 第一部分 Netty提供的一些原生Handler和codecs

本章内容包括(分2次翻译): 1)利用SSL/TLS构建安全的Netty应用 2)构建HTTP/HTTPS的应用 3)处理闲置的连接和超时 4)空格符切分协议和长度切分的协议的解码 5)写入大数据 Netty为各式各样的协议提供了很多译码器和处理器的类,这些类你可以做到拿来即用,可以使你在有些比较麻烦的事件上不用花费不必要的时间和精力,在这个章节我们将会把这些工具介绍给你,且一一分析他们的作用,这些工具包括:支持SSL/TLS和Websocket的工具,也有比HTTP天然的数据压缩更高性能的数据

Netty In Action中国版 - 第二章:第一Netty程序

本章介绍 获得Netty4最新的版本号 设置执行环境,以构建和执行netty程序 创建一个基于Netty的server和client 拦截和处理异常 编制和执行Nettyserver和client 本章将简介Netty的核心概念,这个狠心概念就是学习Netty是怎样拦截和处理异常.对于刚開始学习netty的读者.利用netty的异常拦截机制来调试程序问题非常有帮助.本章还会介绍其它一些核心概念.如server和client的启动以及分离通道的处理程序.本章学习一些基础以便后面章节的深入学习. 本

Netty in Action (二十) 第十章节 codecs

第十章,第十一章序 对于网络而言,数据只是原始字节序列,但是我们的程序将这些字节按照某种方式去组织成我们能够看懂的语言,我们一般称这些信息叫"信息",将信息转换成字节或者从网络中将字节装换成我们能够看懂的信息这些都是我们网络传输中最最常见的任务之一,你可能需要在标准的格式或者协议下工作,例如FTP协议或者Telnet协议,或者是从第三方自定义的专有协议,亦或者是根据字自已的应用去继承一种已有的信息格式 处理将网络中的数据转化成应用数据的组件叫做解码器或者编码器,相对应而言,一个单独的组

Netty in Action (二十四) 第十三章节 UDP的广播事件

本章内容包括: 1)UDP的总览 2)广播应用的一个简单示例 到目前为止,我们使用的所有例子都是基于连接形式的协议,例如TCP,在这个章节中,我们将会聚焦于无连接x形式的协议(User Datagram Protocol UDP),这个协议常常使用于对性能要求极其高但又可以允许少量的丢包的情况存在 我们先讲解一下UDP的概念,讲解一下它的特性和限制,接下来我们会描述一下这个章节示例应用的业务背景,这个示例将会很好的说明如何使用UDP协议的广播特性,我们也会利用解码器和编码器来处理一个POJO,在

Netty in Action (二十二) 第十一章节 第二部分 Netty提供的一些原生Handler和codecs

11.4 Decoding delimited and length-based protocols 如果你使用Netty工作的时候,你经常会遇到使用分隔符或者指定字节数的方法来解码,接下来的一个小节中将讲解Netty在处理这种问题给出的一些具体实现 11.4.1 Delimited protocols 分隔符协议使用某个固定的字符来标记一个信息或者一个信息端的开头和结尾,被分割的消息块我们称之为"帧",由RFC文档定义的有很多正式的规范协议,例如SMTP,POP3,IMAP,Teln

哈佛大学连续十二年蝉联全球第一

 http://www.ebay.com/cln/bxibug0yhsv/-/170897540019/20150203html http://www.ebay.com/cln/woofu-y6bh9aud/-/171089847012/20150203html http://www.ebay.com/cln/gd8xdx4/-/171058211018/20150203html http://www.ebay.com/cln/pwjt-lfbx2kf/-/171058212018/2015

2017-2018-1 20155310 《信息安全系统设计基础》第十二周学习总结

2017-2018-1 20155310 <信息安全系统设计基础>第十二周学习总结 第一周 http://www.cnblogs.com/m20155310/p/7587317.html 第二周 http://www.cnblogs.com/m20155310/p/7618222.html 第三周 http://www.cnblogs.com/m20155310/p/7672424.html 第四周 http://www.cnblogs.com/m20155310/p/7672547.html

Python3快速入门(十二)——NumPy

Python3快速入门(十二)--NumPy 一.NumPy简介 1.NumPy简介 NumPy(Numerical Python) 是 Python 语言的一个扩展程序库,支持大量的维度数组与矩阵运算,同时对数组运算提供了大量的数学函数库.Numpy 是一个运行速度非常快的数学库,内部解除了CPython的GIL(全局解释器锁),运行效率极好,主要用于数组计算,是大量机器学习框架的基础库,NumPy主要包括如下:(1)强大的N维数组对象 ndarray(2)广播功能函数(3)整合 C/C++/