fastjson序列化MessageExt对象问题(1.2.78之前版本)

前言

  无论是kafka,还是RocketMq,消费者方法参数中的MessageExt对象不能被 fastjson默认的方式序列化。

一、查看代码

@Override
public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> msgs,ConsumeConcurrentlyContext context) {try {GiftSendMessage message = JSON.parseObject(msgs.get(0).getBody(),GiftSendMessage.class);UserInfo userInfo = new UserInfo();userInfo.setMemberId(String.valueOf(message.getFromId()));userInfo.setScId(message.getScId());userInfo.setAnchorScid(message.getAnchorScid());userInfo.setAnchorId(message.getAnchorId());userInfo.setGiftSendToId(message.getToId());DrawByGiftSendConfig draw =filter.getGiftIdBySend().get(String.valueOf(message.getGiftId()));GiftSendRequest request = new GiftSendRequest();request.setActivityId(draw.getActivityId());request.setBoxType(draw.getBoxType());request.setGiftOrderId(message.getGiftOrderId());request.setBatch(message.getAmount());request.setSendTime(message.getSendTime());request.setUserInfo(userInfo);request.setPaymentVersion(PAYMENT_VERSION);this.userDrawService.giftSend(request);LOG.info("DRAW BY GIFT SEND WITH SANTA CHECKOUT, MQ-MESSAGE={}, REQUEST={}",JSON.toJSONString(message),JSON.toJSONString(request));} catch (Exception e) {LOG.error("GIFT-SEND-QUEUE CONSUME FATAL ERROR ON PARSING, DROPPED, MSG={},EXCEPTION={}, EXCEPTION-MESSAGE={}",JSON.toJSONString(msgs), e.getClass().getSimpleName(),e.getMessage(), e);} return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
}

二、问题代码

在这里插入图片描述

三、原因分析

  上图中红色方框当中,用的序列化方式为 fastjson,此行代码会抛出异常,导致消费失败,进入重试队列,且没有任何业务日志输出。MQ源码如下:
在这里插入图片描述
如果异常,返回 ConsumeConcurrentlyStatus.RECONSUME_LATER;

结论:无论是kafka,还是RocketMq,消费者方法参数中的MessageExt对象不能被 fastjson默认的方式序列化。

环境:项目采用1.2.31 (最新版本1.2.78)
接下来,我们分析下fastjson序列化的完整过程:
fastjson反序列化的方式默认为采用 get方法、is方法作为序列化属性 字段的,序列化流程如下:
在这里插入图片描述
其中:在获取对象序列化的时候,MessageExt中有返回 ByteBuffer的get方法,代码如下:

public ByteBuffer getStoreHostBytes() {return socketAddress2ByteBuffer(this.storeHost);
} 
//socketAddress2ByteBuffer
public static ByteBuffer socketAddress2ByteBuffer(SocketAddress socketAddress) {ByteBuffer byteBuffer = ByteBuffer.allocate(8);return socketAddress2ByteBuffer(socketAddress, byteBuffer);
}
//socketAddress2ByteBuffer
public static ByteBuffer socketAddress2ByteBuffer(SocketAddress socketAddress, ByteBuffer
byteBuffer) {InetSocketAddress inetSocketAddress = (InetSocketAddress)socketAddress;byteBuffer.put(inetSocketAddress.getAddress().getAddress(), 0, 4);byteBuffer.putInt(inetSocketAddress.getPort());byteBuffer.flip();return byteBuffer;
}

Mq消息在接收到消息时,构造了返回了ByteBuffer对象的方法,该方法是nio中设计用于保存数据到缓冲区的目的。

3.1 ByteBuffer主要的属性,与fastjson的get方法反序列化方式

  • position: 其实是指从buffer读取或写入buffer的下一个元素位置。比如,已经写入buffer 3个元素那那么position就是指向第4个位置,即position设置为3(数组从0开始计);
  • limit:还有多少数据需要从buffer中取出,或还有多少空间可以放入;postition总是<=limit;
  • capacity: 表示buffer本身底层数组的容量。limit绝不能>capacity;

数据结构如下:
在这里插入图片描述

  • get()方法,一字节一字节读;
  • getChar()、getShort()、getInt()、getFloat()、getLong()、getDouble()读取相应字节数的数据;

3.2 最终原因分析得到

  至此:问题显而易见,fastjson在1.2.31及之前,没有提供ByteBuffer 序列化器,所以用了默认的javabean序列化器,而默认的javabean序列化器,又通过get方法反序列化,当遇见ByteBuffer时,ByteBuffer中会先遇到如下方法,getLong():

public long getLong() {return Bits.getLong(this, ix(nextGetIndex(8)), bigEndian);
} //nextGetIndex
final int nextGetIndex(int nb) { // package-privateif (limit - position < nb)throw new BufferUnderflowException();int p = position;position += nb;return p;
}

每次读取position偏移8个字节,而MessageExt中,构建的ByteBuffer存储的时4个字节,所以会报错,完整的堆栈如下:
在这里插入图片描述

四、总结

  1. fastjson 序列化需注意问题,不能序列化RocketMq工具类中MessageExt对象,会报错;
  2. 原因:MessageExt包含ByteBuffer类型的nio包对象,而低版本fastjson没有该类型序列化器(JavaBeanSerializer),使用默认的序列化器;
  3. ByteBuffer中getLong方法,getLong方法的position偏移8个字节,而MessageExt中,构建的ByteBuffer存储的时4个字节,所以会BufferUnderflowException异常。
  4. BufferUnderflowException异常:表示在读取缓冲区时发生了下溢(underflow)的情况。下溢是指尝试从缓冲区中读取比可用数据量更多的数据;
  5. 无论是kafka,还是RocketMq,消费者方法参数中的MessageExt对象不能被 fastjson默
    认的方式序列化;

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【MATLAB】SVMD_ MFE_SVM_LSTM 神经网络时序预测算法

有意向获取代码&#xff0c;请转文末观看代码获取方式~也可转原文链接获取~ 1 基本定义 SVMD_MFE_SVM_LSTM神经网络时序预测算法结合了单变量分解&#xff08;SVMD&#xff09;、多尺度特征提取&#xff08;MFE&#xff09;、聚类后展开支持向量机&#xff08;SVM&#xff09;…

【Ansys Fluent Web 】全新用户界面支持访问大规模多GPU CFD仿真

基于Web的技术将释放云计算的强大功能&#xff0c;加速CFD仿真&#xff0c;从而减少对硬件资源的依赖。 主要亮点 ✔ 使用Ansys Fluent Web用户界面™&#xff08;UI&#xff09;&#xff0c;用户可通过任何设备与云端运行的仿真进行远程交互 ✔ 该界面通过利用多GPU和云计算功…

MIT-BEVFusion系列九--CUDA-BEVFusion部署4 c++解析pytorch导出的tensor数据

目录 创建流打印 engine 信息打印结果内部流程 启动计时功能加载变换矩阵并更新数据&#xff08;重要&#xff09;内部实现 该系列文章与qwe、Dorothea一同创作&#xff0c;喜欢的话不妨点个赞。 在create_core方法结束后&#xff0c;我们的视角回到了main.cpp中。继续来看接下…

[vscode] 1. 在编辑器的标签页下显示文件目录(标签页显示面包屑) 2. 在标题栏上显示当前文件的完整路径

1. 标签页显示面包屑 view->Appearance->Breadcrumbs 2. 在标题栏上显示当前文件的完整路径 搜索 window.title将原来的值activeEditorShort 修改为 activeEditorMedium 参考&#xff1a; vscode在编辑器的标签页下显示文件目录&#xff08;标签页显示面包屑&#xf…

10、电源管理入门之OPP介绍

目录 1. 什么是OPP,怎么用? 2. 系统初始化加载OPP信息 3. 触发使用 4. API介绍 之前的文章设置clock的时候多次提到了(Operating Performance Point)OPP,例如DEVFreq、CPUFreq等,在现代SoC上存在有Power Domain,也可以以Power Domain为单位进行OPP的电压频率定义。 …

C++ 游戏飞机大战, 字符型的

//#define _CRT_SECURE_NO_WARNINGS 1 用于禁止不安全函数的警告 #include<iostream> #include<stdlib.h> #include<string> #include<conio.h> #include<Windows.h> #include<time.h> #include <graphics.h> using namespace std;…

顶会ICLR2024论文Time-LLM:基于大语言模型的时间序列预测

文青松 松鼠AI首席科学家、AI研究院负责人 美国佐治亚理工学院(Georgia Tech)电子与计算机工程博士&#xff0c;人工智能、决策智能和信号处理方向专家&#xff0c;在松鼠AI、阿里、Marvell等公司超10年的技术和管理经验&#xff0c;近100篇文章发表在人工智能相关的顶会与顶刊…

SpringMVC 学习(六)之视图

目录 1 SpringMVC 视图介绍 2 JSP 视图 3 Thymeleaf 视图 4 FreeMarker 视图 5 XSLT 视图 6 请求转发与重定向 6.1 请求转发 (Forward) 6.2 重定向 (Redirect) 7 视图控制器 (view-controller) 1 SpringMVC 视图介绍 在 SpringMVC 框架中&#xff0c;视图可以是一个 J…

字节面试问题

实现三列布局的方法 第一种&#xff1a;可以使用浮动margin 第二种&#xff1a;浮动BFC <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, in…

防御保护:防火墙内容安全

一、IAE&#xff08;Intelligent Awareness Engine&#xff09;引擎 二、深度检测技术(DFI和DPI&#xff09; 1.DPI – 深度包检测技术 DPI主要针对完整的数据包&#xff08;数据包分片&#xff0c;分段需要重组&#xff09;&#xff0c;之后对数据包的内容进行识别。&#x…

10_Vue

文章目录 Vue快速入门Vue的指令Vue的插值表达式V指令v-bind&#xff08;单向绑定&#xff09;v-model&#xff08;双向绑定&#xff09;v-on&#xff08;事件监听&#xff09;v-for&#xff08;循环&#xff09;v-text、v-htmlv-show&#xff08;显示/隐藏&#xff09;v-if&…

JetBrains系列工具,配置PlantUML绘图

PlantUML是一个很强大的绘图工具&#xff0c;各种图都可以绘制&#xff0c;具体的可以去官网看看&#xff0c;或者百度。 PlantUML简述 https://plantuml.com/zh/ PlantUML语言参考指引 https://plantuml.com/zh/guide PlantUML语言是依赖Graphviz进行解析的。Graphviz是开源…

SAP PP学习笔记04 - BOM1 - BOM创建,用途,形式,默认值,群组BOM等

本章开始讲BOM的内容。 1&#xff0c;BOM的定义 &#xff08;Bill of Materials&#xff09; 物料清单&#xff08;Bill of Materials&#xff0c;简称BOM&#xff09;是描述企业产品组成的技术文件。在加工资本式行业&#xff0c;它表明了产品的总装件、分装件、组件、部件、…

python自动化学习--3.8python操作EXCEL文件python日志收集处理

1、Excel文件处理 安装 openpxl 第三方库 openpxl 模块三大组件: 1、工作簿 &#xff08;包含多个sheet工作表&#xff09; 2、工作表 &#xff08;某个数据包含在某个工作表&#xff09; 3、单元格 1、创建excel工作簿 import openpyxl"""Excel表格的创建…

练习 2 Web [ACTF2020 新生赛]BackupFile 1

[ACTF2020 新生赛]BackupFile 1 Web常规题目 首先尝试查找常见的前端页面index.php之类的&#xff0c;没找到 题目有个“BackupFile”——备份文件 尝试用工具遍历查找相关的文件 御剑没扫出来&#xff0c;搜索搭建好dirsearch后&#xff0c;扫出来的index.php.bak 扫描工…

SPA首屏加载速度慢的怎么解决?

什么时首屏加载 首屏时间&#xff0c;指的是浏览器从响应用户输入网址地址&#xff0c;到首屏内容渲染完成的时间&#xff0c;此时整个网页不一定要全部渲染完成&#xff0c;但需要展示当前视图需要的内容。首屏加载可以说是用户体验中最重要的环节 如何计算首屏时间 通过DOM…

可观测性在威胁检测和取证日志分析中的作用

在网络中&#xff0c;威胁是指可能影响其平稳运行的恶意元素&#xff0c;因此&#xff0c;对于任何希望避免任何财政损失或生产力下降机会的组织来说&#xff0c;威胁检测都是必要的。为了先发制人地抵御来自不同来源的任何此类攻击&#xff0c;需要有效的威胁检测情报。 威胁…

【Vue的单选按钮不选中已解决亲测】

伙计&#xff0c;你是否因为后台给vue前端已经传入了对应的单选按钮的数据&#xff0c;为啥还是不选中呢&#xff01;&#xff1f; 这个问题实话我百度乐很多都不能解决我的问题&#xff0c;最后机智如我的发现乐vue的自身的问题&#xff0c;后端返回的数据类型如果是数字int类…

浙江大学主办!2024年第7届信息通信与信号处理国际会议( ICICSP2024)征稿开启!

会议官网 IEEE | ICICSP 2024 学术会议查询-学术会议交流服务平台-爱科会易 (uconf.com)​www.uconf.com/

JavaEE:多线程(3):案例代码

目录 案例一&#xff1a;单例模式 饿汉模式 懒汉模式 思考&#xff1a;懒汉模式是否线程安全&#xff1f; 案例二&#xff1a;阻塞队列 可以实现生产者消费者模型 削峰填谷 接下来我们自己实现一个阻塞队列 1.先实现一个循环队列 2. 引入锁&#xff0c;实现线程安全 …