Netty入门(一):ByteBuf
网络数据的基本单位总是字节。Java NIO 提供了 ByteBuffer 作为它的字节容器,但是这个类使用起来过于复杂,而且也有些繁琐。Netty 的 ByteBuffer 替代品是 ByteBuf,一个强大的实现,既解决了 JDK API 的局限性,又为网络应用程序的开发者提供了更好的 API
ByteBuf优势
- 它可以被用户自定义的缓冲区类型扩展
- 通过内置的复合缓冲区类型实现了透明的零拷贝
- 容量可以按需增长
- 在读和写这两种模式之间切换不需要调用 ByteBuffer 的 flip()方法
- 读和写使用了不同的索引
- 支持方法的链式调用
- 支持引用计数
- 支持池化
ByteBuf实现原理

如图ByteBuf通维护了两个不同的索引:一个用于读取,一个用于写入。
当你从 ByteBuf 读取时,它的 readerIndex 将会被递增已经被读取的字节数。同样地,当你写入 ByteBuf 时,它的writerIndex 也会被递增

当调用readBytes时,readIndex会相应移动length位,如果readIndex移动后大于writeIndex则会抛异常。

当调用writeBytes时,writeIndex会相应移动length位,且通过ensureWritable方法实现自动扩容
其他常用API
| getBytes | 获取可读字节数组 |
| setBytes | 写入字节 |
| discardReadBytes | 废弃已读字节 |
| mark | 标记index |
| reset | 将index重置到之前标记的位置(配合mark使用) |
| isReadable | 如果至少有一个字节可供读取,则返回 true |
| isWritable | 如果至少有一个字节可被写入,则返回 true |
| readableBytes | 返回可被读取的字节数 |
| writableBytes | 返回可被写入的字节数 |
| capacity | 返回 ByteBuf 可容纳的字节数。在此之后,它会尝试再次扩展直到达到 maxCapacity() |
| maxCapacity | 返回 ByteBuf 可以容纳的最大字节数 |
| hasArray | 如果 ByteBuf 由一个字节数组支撑,则返回 true |
| array | 如果 ByteBuf 由一个字节数组支撑则返回该数组;否则,它将抛出一个UnsupportedOperationException 异常 |
ByteBuf缓冲分类
1、Heap buffer(堆缓冲区):
就是将数据存在JVM堆空间中,在没有被池化的情况可以快速分配和释放。
优点:由于数据是存储在JVM堆中,因此可以快速的创建与快速的释放,并且它提供了直接访问内部字节数组的方法。
缺点:每次读写数据时,都需要先将数据复制到直接缓冲区中再进行网路传输。
2、Direct buffer(直接缓冲区):
直接缓冲区,在堆外直接分配内存空间,直接缓冲区并不会占用堆的容量空间,因为它是由操作系统在本地内存进行的数据分配。
优点:在使用Socket进行数据传递时,性能非常好,因为数据直接位于操作系统的本地内存中,所以不需要从JVM将数据复制到直接缓冲区中 。
缺点:因为Direct Buffer是直接在操作系统内存中的,所以内存空间的分配与释放要比堆空间更加复杂,而且速度要慢一些。
注意:
如果你的数据包含在一个在堆上的分配的缓冲区中,那么事实上,在通过套接字发送他之前,jvm将会在内部把你的缓冲区复制到一个直接缓冲区中;这样分配释放就比较浪费资源;
建议:
直接缓冲区并不支持通过字节数组的方式来访问数据。对于后端业务的消息编解码来说,推荐使用HeapByteBuf;对于I/O通信线程在读写缓冲区时,推荐使用DirectByteBuf;
3、Composite Buffer 复合缓冲区:
可以拥有以上两种的缓冲区,通过一种聚合视图来操作底层持有的多种类型Buffer。这种缓冲,jdk nio是没有这种特性的。
ByteBuf主要实现类
pooled:池化,重用ByteBuf对象
Direct:直接内存,内部通过ByteBuffer实现,典型装饰模式
Heap:堆内存,内部持有byte数组
(1)UnpooledDirectByteBuf:
在堆外进行内存分配的非内存池ByteBuf,内部持有ByteBuffer对象,相关操作委托给ByteBuffer实现。
(2)UnpooledHeapByteBuf:
基于堆内存分配非内存池ByteBuf,即内部持有byte数组。
(3)UnpooledUnsafeDirectByteBuf:
和另外一个类UnpooledDirectByteBuf差不多相同,区别在于UnpooledUnsafeDirectByteBuf内部使用基于PlatformDependent相关操作实现ByteBuf,依赖平台。
(4)ReadOnlyByteBufferBuf:
只读ByteBuf,内部持有ByteBuffer对象,相关操作委托给ByteBuffer实现,该ByteBuf限内部使用;
(5)FixedCompositeByteBuf:
用于将多个ByteBuf组合在一起,形成一个虚拟的只读ByteBuf对象,不允许写入和动态扩展。内部使用Object[]将多个ByteBuf组合在一起,一旦FixedCompositeByteBuf对象构建完成,则不会被更改。
(6)CompositeByteBuf:
用于将多个ByteBuf组合在一起,形成一个虚拟的ByteBuf对象,支持读写和动态扩展。内部使用List组合多个ByteBuf。一般使用使用ByteBufAllocator的compositeBuffer()方法,Unpooled的工厂方法compositeBuffer()或wrappedBuffer(ByteBuf... buffers)创建CompositeByteBuf对象。
(7)PooledByteBuf:
基于内存池的ByteBuf,主要为了重用ByteBuf对象,提升内存的使用效率;适用于高负载,高并发的应用中。主要有PooledDirectByteBuf,PooledHeapByteBuf,PooledUnsafeDirectByteBuf三个子类,PooledDirectByteBuf是在堆外进行内存分配的内存池ByteBuf,PooledHeapByteBuf是基于堆内存分配内存池ByteBuf,PooledUnsafeDirectByteBuf也是在堆外进行内存分配的内存池ByteBuf,区别在于PooledUnsafeDirectByteBuf内部使用基于PlatformDependent相关操作实现ByteBuf,具有平台相关性。
Netty入门(一):ByteBuf的更多相关文章
- 网络编程Netty入门:ByteBuf分析
目录 Netty中的ByteBuf优势 NIO使用的ByteBuffer有哪些缺点 ByteBuf的优势和做了哪些增强 ByteBuf操作示例 ByteBuf操作 简单的Demo示例 堆内和堆外内存 ...
- Netty入门(四)ByteBuf 字节级别的操作
Netty 中使用 ByteBuf 代替 Java NIO 提供的 ByteBuffer 作为字节的容器. 一.索引 ByteBuf 提供两个指针变量支持读和写操作,读操作使用 readerInde ...
- Netty入门之HelloWorld
Netty系列入门之HelloWorld(一) 一. 简介 Netty is a NIO client server framework which enables quick and easy de ...
- Netty入门
一.NIO Netty框架底层是对NIO的高度封装,所以想要更好的学习Netty之前,应先了解下什么是NIO - NIO是non-blocking的简称,在jdk1.4 里提供的新api,他的他的特性 ...
- netty入门(一)
1. netty入门(一) 1.1. 传统socket编程 在任何时候都可能有大量的线程处于休眠状态,只是等待输入或者输出数据就绪,这可能算是一种资源浪费. 需要为每个线程的调用栈都分配内存,其默认值 ...
- Netty入门(三)之web服务器
Netty入门(三)之web服务器 阅读前请参考 Netty入门(一)之webSocket聊天室 Netty入门(二)之PC聊天室 有了前两篇的使用基础,学习本文也很简单!只需要在前两文的基础上稍微改 ...
- Netty入门(一)之webSocket聊天室
一:简介 Netty 是一个提供 asynchronous event-driven (异步事件驱动)的网络应用框架,是一个用以快速开发高性能.高可靠性协议的服务器和客户端. 换句话说,Netty 是 ...
- Netty入门(1) - 简介
什么是Netty? Netty 是一个利用 Java 的高级网络的能力,隐藏其背后的复杂性而提供一个易于使用的 API 的客户端/服务器框架. Tomcat和Netty有什么区别? Netty和Tom ...
- Netty入门教程——认识Netty
什么是Netty? Netty 是一个利用 Java 的高级网络的能力,隐藏其背后的复杂性而提供一个易于使用的 API 的客户端/服务器框架. Netty 是一个广泛使用的 Java 网络编程框架(N ...
- Netty 系列(三)Netty 入门
Netty 系列(三)Netty 入门 Netty 是一个提供异步事件驱动的网络应用框架,用以快速开发高性能.高可靠性的网络服务器和客户端程序.更多请参考:Netty Github 和 Netty中文 ...
随机推荐
- electron-ipc通信性能分析
electron-ipc通信性能分析 electron的主进程和渲染进程间通信方案 ipc通信 借助外部存储通信(通过ipc通知其它进程去读取) 方案描述 ipc通信 使用 主进程 ==> 渲染 ...
- vscode中html和vue没有自动补全,需要怎么配置
先安装HTML Snippets插件 点击 文件-首选项-设置,然后根据以下操作 然后在setting.json中加入以下代码 然后就有提示了
- .Net Core 3.1简单搭建微服务
学如逆水行舟,不进则退!最近发现微服务真的是大势所趋,停留在公司所用框架里已经严重满足不了未来的项目需要了,所以抽空了解了一下微服务,并进行了代码落地. 虽然项目简单,但过程中确实也学到了不少东西. ...
- 31、DNS介绍
[root@centos6 ~]# dig @8.8.8.8 www.baidu.com +trace ; <<>> DiG 9.8.2rc1-RedHat-9.8.2-0.3 ...
- 面试官:spring中定义bean的方法有哪些?我一口气说出了12种,把面试官整懵了。
前言 在庞大的java体系中,spring有着举足轻重的地位,它给每位开发者带来了极大的便利和惊喜.我们都知道spring是创建和管理bean的工厂,它提供了多种定义bean的方式,能够满足我们日常工 ...
- js实现返回顶部按钮
html: <div class="box"></div> <div class="box1"></div> & ...
- NoSql非关系型数据库之MongoDB应用(三):MongoDB在项目中的初步应用
业精于勤,荒于嬉:行成于思,毁于随. 我们可以结合相关的IDE做一个简单的增删改查了,实现MongoDB在项目中的初步应用. 前提是安装了MongoDB服务和MongoDB可视化工具,没有安装的可以点 ...
- APDU:APDU常用指令
APDU= ApplicationProtocol data unit, 是智能卡与智能卡读卡器之间传送的信息单元, (给智能卡发送的命令)指令(ISO 7816-4规范有定义) CLA INS P1 ...
- AOP面向切面的实现
AOP(Aspect Orient Programming),我们一般称为面向方面(切面)编程,作为面向对象的一种补充,用于处理系统中分布于各个模块的横切关注点,比如事务管理.日志.缓存等等. AOP ...
- mybatis源码简单分析
mybatis入门介绍 /** * 1. 接口式编程 * 原生: Dao =====> DaoImpl * mybatis : Mapper =====> xxxMapper * 2. S ...