网络数据的基本单位总是字节。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的更多相关文章

  1. 网络编程Netty入门:ByteBuf分析

    目录 Netty中的ByteBuf优势 NIO使用的ByteBuffer有哪些缺点 ByteBuf的优势和做了哪些增强 ByteBuf操作示例 ByteBuf操作 简单的Demo示例 堆内和堆外内存 ...

  2. Netty入门(四)ByteBuf 字节级别的操作

     Netty 中使用 ByteBuf 代替 Java NIO 提供的 ByteBuffer 作为字节的容器. 一.索引 ByteBuf 提供两个指针变量支持读和写操作,读操作使用 readerInde ...

  3. Netty入门之HelloWorld

    Netty系列入门之HelloWorld(一) 一. 简介 Netty is a NIO client server framework which enables quick and easy de ...

  4. Netty入门

    一.NIO Netty框架底层是对NIO的高度封装,所以想要更好的学习Netty之前,应先了解下什么是NIO - NIO是non-blocking的简称,在jdk1.4 里提供的新api,他的他的特性 ...

  5. netty入门(一)

    1. netty入门(一) 1.1. 传统socket编程 在任何时候都可能有大量的线程处于休眠状态,只是等待输入或者输出数据就绪,这可能算是一种资源浪费. 需要为每个线程的调用栈都分配内存,其默认值 ...

  6. Netty入门(三)之web服务器

    Netty入门(三)之web服务器 阅读前请参考 Netty入门(一)之webSocket聊天室 Netty入门(二)之PC聊天室 有了前两篇的使用基础,学习本文也很简单!只需要在前两文的基础上稍微改 ...

  7. Netty入门(一)之webSocket聊天室

    一:简介 Netty 是一个提供 asynchronous event-driven (异步事件驱动)的网络应用框架,是一个用以快速开发高性能.高可靠性协议的服务器和客户端. 换句话说,Netty 是 ...

  8. Netty入门(1) - 简介

    什么是Netty? Netty 是一个利用 Java 的高级网络的能力,隐藏其背后的复杂性而提供一个易于使用的 API 的客户端/服务器框架. Tomcat和Netty有什么区别? Netty和Tom ...

  9. Netty入门教程——认识Netty

    什么是Netty? Netty 是一个利用 Java 的高级网络的能力,隐藏其背后的复杂性而提供一个易于使用的 API 的客户端/服务器框架. Netty 是一个广泛使用的 Java 网络编程框架(N ...

  10. Netty 系列(三)Netty 入门

    Netty 系列(三)Netty 入门 Netty 是一个提供异步事件驱动的网络应用框架,用以快速开发高性能.高可靠性的网络服务器和客户端程序.更多请参考:Netty Github 和 Netty中文 ...

随机推荐

  1. Springboot WebFlux集成Spring Security实现JWT认证

    我最新最全的文章都在南瓜慢说 www.pkslow.com,欢迎大家来喝茶! 1 简介 在之前的文章<Springboot集成Spring Security实现JWT认证>讲解了如何在传统 ...

  2. 95、配置ntp服务器

    95.1.ntp简介: ntp服务使用的是udp的123端口,如果开启了防火墙要记得放开这个端口: NTP(Network Time Protocol,网络时间协议)是用来使网络中的各个计算机时间同步 ...

  3. Visual Studio 2010 SP1 中文升级补丁ISO完整版下载 (含多国语言)

    最近事情比较多,差点忘记了这个VS2010 SP1的升级补丁更新了,程序员们赶快更新吧!这次发布的SP1包含了下列语言:英文,简体中文,繁体中文,法语,德语,印度语,日语,韩语,俄语以及西班牙语. V ...

  4. layui table 表格上添加日期控件

    方法一: var tableInit = table.render({ elem: '#tbtxrz' , method: 'post' , data: jsonData , height: &quo ...

  5. hdu 2842 Chinese Rings 矩阵快速幂

    分析: 后面的环能不能取下来与前面的环有关,前面的环不被后面的环所影响.所以先取最后面的环 设状态F(n)表示n个环全部取下来的最少步数 先取第n个环,就得使1~n-2个环属于被取下来的状态,第n-1 ...

  6. 万字长文肝Git--全流程知识点包您满意【建议收藏】

    您好,我是码农飞哥,感谢您阅读本文,欢迎一键三连哦. 本文将首先介绍在本地搭建GitLab服务,然后重点介绍Git的常用命令,Git的核心概念以及冲突处理,最后介绍Git与SVN的区别 干货满满,建议 ...

  7. spring boot j集成seagger 加入拦截器后 swagger 不能访问

    一开始我是这样排除拦截的,但是发现没用 后来我发现swagger的真实访问路径是这样的 转自: https://blog.csdn.net/ab1991823/article/details/7906 ...

  8. centos7 php开发环境安装-composer

    1.安装composer cd /usr/local/src curl -sS https://getcomposer.org/installer | php mv composer.phar /us ...

  9. 密码学系列之:memory-bound函数

    密码学系列之:memory-bound函数 目录 简介 内存函数 内存受限函数 内存受限函数的使用 简介 memory-bound函数可以称为内存受限函数,它是指完成给定计算问题的时间主要取决于保存工 ...

  10. ESP32省电模式连接WIFI笔记

    基于ESP-IDF4.1版本 main.c文件如下: #include <string.h> #include "freertos/FreeRTOS.h" #inclu ...