netty入门-7 ByteBuf

news2024/11/24 19:18:12

文章目录

  • 前言
  • ByteBuf
    • 结构
    • 池化与非池化
    • 创建(直接内存/堆内存)
    • 写入和读取
    • 释放
    • 零拷贝,slice,duplicate, copy,Composite
  • 结语

前言

ByteBuf这部分视频讲的更为详细。
主要参考视频。

ByteBuf

结构

首先这个东西的结构与ByteBuffer十分相似。
就是一个带指针的字节容器。
在这里插入图片描述

有读指针(read index),写指针(write index),和容量(capacity)。
我们每读取1字节,read index就加1
每写1字节,write index加1
可读范围就是write index - read index,读指针到了写指针的位置就表明没有数据可读。
read index之前一般就是已读字节
write index如果没到capacity,则write indexcapacity之间表示可写字节。
还有就是ByteBuf可以扩容。内部有变量maxCapacity,若扩容时会超过这个值会报错。

池化与非池化

池化,听着有点陌生。
数据库连接池,线程池。都是池化来达到重用的思路。
ByteBuf也一样。
正常非池化意味着每次使用都要创建ByteBuf实例。
而池化则可以直接重用池中的ByteBuf实例。
直接内存的申请与释放是比较消耗性能的。所以采用池化可以省掉这部分开销。且省掉申请空间的时间。

创建(直接内存/堆内存)

可以创建基于堆的和基于直接内存的ByteBuf

//默认池化,基于直接内存
ByteBuf buffer = ByteBufAllocator.DEFAULT.buffer(10);
//池化,基于堆内存
ByteBuf buffer = ByteBufAllocator.DEFAULT.heapBuffer(10);
//池化,基于直接内存
ByteBuf buffer = ByteBufAllocator.DEFAULT.directBuffer(10);

直接内存不受JVM GC管理,需要手动释放。
直接内存申请释放比较消耗性能(所以推荐池化)。
直接内存的优势在于读写性能高

写入和读取

这里的读取写入不需要切换读写模式
读取的话同样有mark和reset方法

buffer.markReaderIndex();
buffer.resetReaderIndex();
buffer.getInt();//读取一个int值,不改变指针位置

基本使用和ByteBuffer一样,读写指针的变化这里类似于NIO的ByteBuffer。不再赘述

这里主要说一个问题。
比如我们使用writeInt方法,int我们知道是32位的,4个字节。例如写入一个数字8,writeInt(8),那么我们如果读取使用readByte(),表示读一个字节,前三次就会读出0,第四次才会读出8,相当于你把32位的int值分四次,每次读8位即一个字节。使用readInt就会直接读32位,不会出现上面的问题。
所以一般怎么写怎么读。

下面是老师讲义里的API表格
读取的API类似

方法签名含义备注
writeBoolean(boolean value)写入 boolean 值用一字节 01|00 代表 true|false
writeByte(int value)写入 byte 值
writeShort(int value)写入 short 值
writeInt(int value)写入 int 值Big Endian,即 0x250,写入后 00 00 02 50
writeIntLE(int value)写入 int 值Little Endian,即 0x250,写入后 50 02 00 00
writeLong(long value)写入 long 值
writeChar(int value)写入 char 值
writeFloat(float value)写入 float 值
writeDouble(double value)写入 double 值
writeBytes(ByteBuf src)写入 netty 的 ByteBuf
writeBytes(byte[] src)写入 byte[]
writeBytes(ByteBuffer src)写入 nio 的 ByteBuffer
int writeCharSequence(CharSequence sequence, Charset charset)写入字符串

释放

我们使用直接内存的ByteBuf需要我们自己来释放
Netty 这里采用了引用计数法来控制回收内存,每个 ByteBuf 都实现了 ReferenceCounted 接口

  • 每个 ByteBuf 对象的初始计数为 1
  • 调用 release 方法计数减 1,如果计数为 0,ByteBuf 内存被回收
  • 调用 retain 方法计数加 1,表示调用者没用完之前,其它 handler 即使调用了 release 也不会造成回收
  • 当计数为 0 时,底层内存会被回收,这时即使 ByteBuf 对象还在,其各个方法均无法正常使用

我们一般ByteBuf会经过多个ChannelHandler的传递,所以我们不能直接
release。而是在最后使用ByteBuf的地方释放。
老师这里说的是谁是最后使用者,谁负责 release
讲义的详细分析

  • 起点,对于 NIO 实现来讲,在 io.netty.channel.nio.AbstractNioByteChannel.NioByteUnsafe#read 方法中首次创建 ByteBuf 放入 pipeline(line 163 pipeline.fireChannelRead(byteBuf))
  • 入站 ByteBuf 处理原则
    • 对原始 ByteBuf 不做处理,调用 ctx.fireChannelRead(msg) 向后传递,这时无须 release
    • 将原始 ByteBuf 转换为其它类型的 Java 对象,这时 ByteBuf 就没用了,必须 release
    • 如果不调用 ctx.fireChannelRead(msg) 向后传递,那么也必须 release
    • 注意各种异常,如果 ByteBuf 没有成功传递到下一个 ChannelHandler,必须 release
    • 假设消息一直向后传,那么 TailContext 会负责释放未处理消息(原始的 ByteBuf)
  • 出站 ByteBuf 处理原则
    • 出站消息最终都会转为 ByteBuf 输出,一直向前传,由 HeadContext flush 后 release
  • 异常处理原则
    • 有时候不清楚 ByteBuf 被引用了多少次,但又必须彻底释放,可以循环调用 release 直到返回 true

零拷贝,slice,duplicate, copy,Composite

结语

ByteBuf是最后一部分。
还有一个就是Netty提供了拆包器了来解决粘包半包问题。下篇来说
协议设计放在下下篇。

再后面就是Netty的应用了。这块不一定会写,想看可以去看视频
比如实现简单的客户端服务端消息收发,通信协议,实现一个聊天等应用。就是说基本的使用来实现我们的需求。

然后就是其实NIO部分的IO模型没写,因为这个属于网上能找到很多资料。
NIO的零拷贝的逐步优化可能写一下,老师讲义里写的挺好的。
Netty ByteBuf的零拷贝这里仅提了概念,后续写了NIO的和ByteBuf的还有直接内存一块写一下,加深下理解。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1953144.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C# Task.WaitAll 的用法

目录 简介 1.WaitAll(Task[], Int32, CancellationToken) 2.WaitAll(Task[]) 3.WaitAll(Task[], Int32) 4.WaitAll(Task[], CancellationToken) 5.WaitAll(Task[], TimeSpan) 结束 简介 Task.WaitAll 是 C# 中用于并行编程的一个的方法,它属于 System.Threa…

开始尝试从0写一个项目--后端(三)

器材管理 和员工管理基本一致,就不赘述,展示代码为主 新增器材 表设计: 字段名 数据类型 说明 备注 id bigint 主键 自增 name varchar(32) 器材名字 img varchar(255) 图片 number BIGINT 器材数量 comment VARC…

Elasticsearch 使用误区之三——分片设置不合理

Elasticsearch 是一个强大的搜索和分析引擎,它通过将数据分散到多个节点的分片中来进行分布式处理。 本文将探讨分片大小和策略的概念,以优化 Elasticsearch 的性能并防止过度分片或分片过大等问题。 先看个分片设置不合理的真实企业案例: 10…

陶晶驰串口屏使用记录与教程

首先把串口屏想象成和正点原子usmart调试程序一样的程序,串口屏主芯片有些是GD32 STM32都是主流单片机,里面下载了一些固件形成了现在的操作系统 其实我更喜欢把他们(usmart,串口屏主程序,micropython,at指…

uniapp vue3 使用画布分享或者收藏功能

使用HBuilder X 开发小程序,大多数的画布插件很多都是vue2的写法,vue3的很少 我自己也试了很多个插件,但是有一些还是有问题,不好用 海报画板 - DCloud 插件市场 先将插件导入项目中 自己项目亲自用过,功能基本是完善…

GraphRAG:基于实体的本地搜索方法:知识图谱与非结构化数据的融合

GraphRAG:基于实体的本地搜索方法:知识图谱与非结构化数据的融合 在自然语言处理和信息检索领域,如何有效地结合结构化知识和非结构化文本数据一直是一个重要的研究方向。本文介绍一种基于实体的本地搜索方法,该方法巧妙地融合了知识图谱中的结构化数据和输入文档中…

优化冗余代码:提升前端项目开发效率的实用方法

目录 前言代码复用与组件化模块化开发与代码分割工具辅助与自动化结束语 前言 在前端开发中,我们常常会遇到代码冗余的问题,这不仅增加了代码量,还影响了项目的可维护性和开发效率。还有就是有时候会接到紧急业务需求,要求立马完…

打造一篇完美的【数学建模竞赛论文】:从准备到撰写的全面指南

目录 一、赛前准备 1.1 报名与纪律要求 1.2 MD5码上传 1.3 竞赛准备 1.4 时间分配 二、论文格式规范 2.1 摘要 2.2 参考文献 2.3 排版要求 三、建模过程与方法 3.1 问题分析与模型假设 3.2 模型构建与求解 3.3 结果分析与检验 四、论文撰写技巧 4.1 论文结构 4…

Redisson中分布式锁继承体系

直接上图 画了好久 关于非公平锁和公平锁中差异化函数如tryLockInnerAsyc 和unsubscribe还没有时间进行探索,这应该是公平锁和非公平锁之间的差异所在。 说一说Redisson中的类之间关系设计 参考抽象类实现接口_一个抽象之类 如果要实现某个接口怎么办-CSDN博客 众…

电脑文件误删除如何恢复?数据恢复第一步是什么?这五点要第一时间处理!

电脑文件误删除如何恢复?数据删除恢复的第一时间要做什么,你知道吗? 在使用电脑的过程中,误删除重要文件的情况时有发生。面对这种情况,不必过于慌张,因为有多种方法可以帮助你恢复误删除的文件。以下是恢复…

金字塔监督在人脸反欺骗中的应用

介绍 论文地址:https://arxiv.org/pdf/2011.12032.pdf 近年来,人脸识别技术越来越普及。在智能手机解锁和进出机场时,理所当然地会用到它。人脸识别也有望被用于管理今年奥运会的相关人员。但与此同时,人们对人脸欺骗的关注度也…

醒醒,别睡了...讲《数据分析pandas库》了—/—<3>

直接上知识点 一、 1、新建数据框时建立索引 所有的数据框默认都已经使用从 0 开始的自然数索引,因此这里的"建立”索引指的是自定 df pd.DataFrame( {varl : 1.0, var2 :[1,2,3,4], var3 :[test,python,test,hello] , var4 : cons} , index [0,1,2,3]) …

【ESP32 IDF SPI硬件驱动W25Q64】

目录 SPISPI介绍idf配置初始化配置通信 驱动代码 SPI SPI介绍 详细SPI介绍内容参考我之前写的内容【ESP32 IDF 软件模拟SPI驱动 W25Q64存储与读取数组】 idf配置 初始化配置 spi_bus_initialize() 参数1 :spi几,例如spi2,spi3 参数2:…

MySQL体系结构与查询执行流程详解

MySQL 体系结构与查询执行过程详解 MySQL 是一个采用单进程多线程架构模式的关系型数据库管理系统。本文将详细介绍 MySQL 的体系结构及其查询语句的执行过程,并探讨性能优化的关键点。 MySQL 体系结构 MySQL 的架构为 Client-Server 架构。总体上,我们可以将 MySQL 的体系…

python—pandas基础(2)

文章目录 列操作修改变量列筛选变量列使用.loc[](基于标签)使用.iloc[](基于整数位置)使用.filter()方法 删除变量列添加变量列 变量类型的转换Pandas 支持的数据类型在不同数据类型间转换 建立索引新建数据框时建立索引读入数据时建立索引指…

如何在宝塔面板给域名配置 SSL 证书

首先需要有证书 这里以阿里云为例 1. 首先进入到 SSL 证书管理控制台 选择个人测试证书,并点击购买 免费的可以使用三个月。 购买完成之后回到控制台。 点击创建证书,将标红的地方填写,其他默认就好。 然后提交审核就行。 这里需要对域名…

JS逆向高级爬虫

JS逆向高级爬虫 JS逆向的目的是通过运行本地JS的文件或者代码,以实现脱离他的网站和浏览器,并且还能拿到和浏览器加密一样的效果。 10.1、编码算法 【1】摘要算法:一切从MD5开始 MD5是一个非常常见的摘要(hash)逻辑. 其特点就是小巧. 速度快. 极难被破解. 所以,…

图像生成中图像质量评估指标—FID介绍

文章目录 1. 背景介绍2. 实际应用3. 总结和讨论 1. 背景介绍 Frchet Inception Distance(\textbf{FID})是一种衡量生成模型性能的指标,它基于Inception网络提取的特征来计算模型生成的图像与真实图像集合之间的距离。 FID利用了Inception模…

repo中的default.xml文件project name为什么一样?

文章目录 default.xml文件介绍为什么 name 是一样的,path 不一样?总结 default.xml文件介绍 在 repo 工具的 default.xml 文件中,定义了多个 project 元素,每个元素都代表一个 Git 仓库。 XML 定义了多个不同的 project 元素&…

64.隐藏指定模块

免责声明:内容仅供学习参考,请合法利用知识,禁止进行违法犯罪活动! 内容参考于:易道云信息技术研究院 上一个内容:63.利用PEB获取模块列表 效果图: 隐藏模块简单实现: #include …