http接口返回中文数据偶现乱码问题排查

2022-07-17 11:47:11

目录

问题产生

 排查过程

 问题分析

结论


问题产生

本地环境(spring框架)调试一个http接口,数据从数据库获取并缓存到redis,偶现接口返回的数据有乱码,如下图

 排查过程

  1. 去掉缓存,每次都从数据库获取,不会产生乱码
  2. 每次都从缓存获取,不会乱码(前提缓存的数据都是正确的)
  3. 只使用测试环境,不管数据从缓存还是从数据库都不会产生乱码
  4. 只使用本地开发环境,不管数据从缓存还是从数据库都不会产生乱码
  5. 测试环境和本地环境都启动,每次请求都删除缓存,让缓存重新生成,偶现乱码
  6. 继续排查如何生成的缓存,如下图所示,先发送了mq再将缓存放入redis
  7. 发送mq的过程,如下图所示,将需要发送的内容转为字节码然后发送出去
  8. 消费mq的过程,如下图所示,将收到的字节数据转换为String并set到redis中(测试环境和本地环境都可能消费mq)

 问题分析

乍一看,这个流程没什么问题,测试环境也用了很久了,没遇到过,但是在本地开发的时候却遇到了,十分奇怪。。。由于消息的消费是不确定在测试机器还是本地机器,所以会不会是两边的消息不一样导致的呢?带着这个疑问,看了下java源码。代码中

dataStr.getBytes()

最终会调用到

new String(message.getData())

最终会调用到

可以看到,两段代码都使用了

String csn = Charset.defaultCharset().name();

 来获取默认的编码格式来进行字符串的编码和解码

故在代码中加上log

重新部署进行测试

真相大白,如下图所示

本地日志

 测试环境日志

结论

  1. 此问题是由字符串转换导致
  2. 字符串转字节码,再由字节码转字符串,两次转换的编码不同导致数据乱码
  3. mq的发送方都是本地开发机器,所以字符串转为字节码的编码都是本地的GBK编码
  4. 由于mq的消费方,是不确定的,导致有时候是本地开发机器消费有时候是测试环境机器消费,并且两边的环境的默认的编码不一样,所以就导致字节码转换为字符串的时候的编码不一样,就直接导致set进redis缓存的数据是不一样的,也就是偶现乱码
  5. 再次提醒大家开发环境和测试环境,一定要分开,做到环境隔离
  • 作者:starryninglong
  • 原文链接:https://blog.csdn.net/starryninglong/article/details/119420433
    更新时间:2022-07-17 11:47:11