Json打印MQ对象问题

文章讲述了在使用fastjson处理Kafka或RocketMQ消息时,由于MessageExt中的ByteBuffer无法被fastjson的默认序列化方式处理,导致消费失败并进入重试队列。分析了问题的原因在于fastjson在1.2.31版本之前缺乏ByteBuffer序列化支持。
摘要由CSDN通过智能技术生成

一、代码

@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方法,代码如下:
在这里插入图片描述
Mq消息在接收到消息时,构造了返回了ByteBuffer对象的方法,该方法是nio中设计用于保存数
据到缓冲区的目的。

主要的属性如下:

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

在这里插入图片描述

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

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

四、fastjson序列化

fastjson序列化的过程源码这里就不分析了,有兴趣自己看一下,总之是要获取对应的序列化器;

上面方法可证明,fastjson序列化是依赖的java方法:

  • getXxx();
  • boolean isXxx();
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值