0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

一行MD5居然让小伙伴都回不了家!

马哥Linux运维 来源:马哥Linux运维 2023-07-04 11:20 次阅读

需求是什么

这里不再介绍具体的业务。简而言之,有两个接口(查询、确认)对前端页面提供服务。

查询接口返回的数据依赖于本地数据与外部接口计算后的结果,也就是页面展示的是数据快照。确认接口是按照页面的展示结果请求外部接口。

考虑到用户打开展示页面时的数据与提交操作可能间隔很久,实际请求时结果已发生变化,而这种操作会影响业务结果。因此在提交时会进行一次 check,如果发现数据发生变化需要提示页面进行刷新。

为了方便大家理解,我简单的画了个图,毕竟上面太啰嗦了。

查询接口:

3100c474-19aa-11ee-962d-dac502259ad0.png

确认接口:

3110d616-19aa-11ee-962d-dac502259ad0.png

虽然这个图有点草率,但是相信看到这里的小伙伴(默认都是聪明的)都对需求了然于胸了。

我怎么搞得

掰扯了半天,我们的主角 MD5 还没有出场,别着急,马上就来了。

你也可以想想,这个场景和 MD5 是怎么扯上关系的呢?

可以看出,这里需要前端将查询接口的返回值重新组装作为确认接口的入参。而后端需要再次走数据聚合的逻辑与前端传过来的业务值进行比较,如果不匹配则提示页面需要刷新。

一切看起来都顺理成章,那么小编遇到了什么问题呢?

简单来说有两点:

  • 前端同学表示值不好传,因为这个页面比较复杂,具体原因小编也没深究,可能是被糊弄了。
  • 后端同学(也就是小编)发现,这样查询接口和确认接口耦合很严重,如果确认接口需要新的入参,那么就需要改动查询接口。随着查询接口逻辑越来越复杂,确认接口的一个入参就需要一层一层的传过来。很不友好。

呵呵,机智的小编灵机一动,便想到了了MD5,看看百度百科怎么说:

MD5 信息摘要算法(英语:MD5 Message-Digest Algorithm),一种被广泛使用的密码散列函数,可以产生出一个 128 位(16 字节)的散列值(hash value),用于确保信息传输完整一致。

一图胜千言:

315f7abe-19aa-11ee-962d-dac502259ad0.png

在工程,它差不多就是这么用。

String md5= Md5Utils.get(String source);

可能有聪明的小伙伴会说了,这是散列函数存在哈希碰撞,不同的字符串也有可能生成相同的哈希值。

是的没错,但是在小编的业务场景中,这种出现的概率微乎其微,忽略不计,解释权归小编所有。

那么具体怎么做的呢,还是看图说话.

改造后的查询接口:

316e064c-19aa-11ee-962d-dac502259ad0.png

改造后的确认接口:

318ed354-19aa-11ee-962d-dac502259ad0.png

我们需要对查询接口返回的业务集关键属性进行组合哈希,这样可以生成数据快照值。确认接口无需再传入业务集合,只需要传入数据快照值,后端进行对比即可知道是否发生变更。

一切都是那么的美好,接下来就到了动人心魄的编码环节。话不多说,小编的项目中引入了hutool包,什么你不知道糊涂包?

31abc0a4-19aa-11ee-962d-dac502259ad0.png

真不错,果然是效率担当,一行代码就搞定了。

/**
*生成数据哈希
*/
privateStringgenerateSnapShotHash(AcceptListQueryWrapResultDTOwrapResultDTO){
StringBuilderbuilder=newStringBuilder();
for(AcceptListQueryResultDTOitem:wrapResultDTO.getAllList()){
builder.append(item.getQuotationId()).append(item.getOperateType()).append(item.getPriceTypeCN());
}
returnMD5.create().digestHex16(builder.toString());
}

请各位看官记住这行代码:

MD5.create().digestHex16(builder.toString());

毕竟它就是糊弄你点进来的罪魁祸首。

出了什么事

当小编开发完以后,开心的部署在了测试环境。和前端联调的时候,发现第一次请求总是超时 ???

一想可能是mock平台的问题,毕竟三方的查询接口还没开发完成,就不以为然。请注意,只是第一次超时。同样的请求参数第二次光速返回。呵呵,你说不是环境的问题,小编自己都不大信呢。

友方的接口开发完了,小编期待的换上了对方的接口。结果现实给了小编一记左勾拳,还是第一次超时。这不科学?于是小编对自身产生了怀疑?难道不是环境的问题?

于是连忙在本地测试了一下,居然是光速返回。作为自信的人一定不是代码的问题,那么这个锅往哪里甩呢?又臭又硬的小编狠狠的思考了一分钟,又将锅甩给了业务网关(统一接收HTTP请求)肯定是它的毛病,毕竟测试环境的网关出问题很常见。

于是开开心心的准备上预发了。上了预发绝对没问题!!!小编信誓旦旦的对QA说道。

上帝为你关上一扇门的同时也会为你关上一扇窗,预发环境第一次还是超时!!!小编觉得很惭愧对不起一起上线的小伙伴,毕竟大家都准备十点下机了。

小编陷入了沉思中。。。

怎么修好的

排查了预发环境的接口,友方的杰夫接口TP99只有几毫秒,网关也没有问题,也许是数据库的原因,排查发现也没有问题。顿时,小编又迷茫了。

山重水复疑无路柳暗花明又一村,机智的小编想到了国内知名厂商开源的一款java诊断工具Arthas,利用它可以查看方法详细耗时。点我查看 主动打开另一扇窗。

当你遇到以下类似问题而束手无策时,Arthas可以帮助你解决:

  • 这个类从哪个 jar 包加载的?为什么会报各种类相关的 Exception?
  • 我改的代码为什么没有执行到?难道是我没 commit?分支搞错了?
  • 遇到问题无法在线上 debug,难道只能通过加日志再重新发布吗?
  • 线上遇到某个用户的数据处理有问题,但线上同样无法 debug,线下无法重现!
  • 是否有一个全局视角来查看系统的运行状况?
  • 有什么办法可以监控到 JVM 的实时运行状态?
  • 怎么快速定位应用的热点,生成火焰图?
  • 怎样直接从 JVM 内查找某个类的实例?

由于预发环境还是比较麻烦,于是小编在测试环境准备好了arthas环境。

下面简单介绍下使用步骤:

  • 下载全量包 arthas-bin.zip
  • 解压
  • chmod -777 arthas-boot.jar
  • 启动 sudo -u admin -EH java -jar /home/export/App/arthas-boot.jar

当看到图标出现时,即启动成功。具体使用方法可以查看官网,此处不再赘述。

我们使用trace命令查看方法耗时,同时在页面请求该查询接口。

trace --skipJDKMethod false com.jd.universal.inquiry.service.protocol.jsf.AcceptListWebErpServiceImpl queryList

31fed596-19aa-11ee-962d-dac502259ad0.png

可以看到这行生成数据快照的方法,耗时占整个接口的99.57%,紧接着我们继续监控generateSnapShotHash方法:

trace --skipJDKMethod false com.jd.universal.inquiry.service.protocol.jsf.AcceptListWebErpServiceImpl generateSnapShotHash

321e76c6-19aa-11ee-962d-dac502259ad0.png

可以看到方法的耗时都集中在

[99.99% 36562.318173ms ] cn.hutool.crypto.digest.MD5:create() #103

接着再次页面点击请求操作,出现以下情况:

3251a14a-19aa-11ee-962d-dac502259ad0.png

可以看到后面多次请求 cn.hutool.crypto.digest.MD5:create()方法耗时仅不到一毫秒。和我们之前遇到的状况一致。此时已确定是这行MD5导致的第一次加载很慢。

虽然原因找到了,但是还是得看下为什么这行代码只有在第一次时这么慢,于是我们进入该方法看看它到底搞什么幺蛾子。

可以看到初始化方法如下:

326a5b0e-19aa-11ee-962d-dac502259ad0.png

由于现象是程序第一次运行很慢,后续很快,根据小编多年的写/修BUG经验怀疑是这段初始化中存在静态加载。

32971748-19aa-11ee-962d-dac502259ad0.png

MessageDigest是JDK自带的类,为应用程序提供摘要算法的,这里我们关注点就落在了上面的一行。我们点进去看一下:

果然我们看到了他在尝试加载BouncyCastle库,我们来看一下这个库的介绍:

BouncyCastle(轻量级密码术包)是一种用于 Java 平台的开放源码的轻量级密码术包;Bouncycstle 包含了大量的密码算法,其支持椭圆曲线密码算法,并提供 JCE 1.2.1 的实现。

32a6343a-19aa-11ee-962d-dac502259ad0.png

所以问题的答案就呼之欲出了,随着源码的深入,我们看到:

privatevoidsetup()
{
loadAlgorithms(DIGEST_PACKAGE,DIGESTS);

loadAlgorithms(SYMMETRIC_PACKAGE,SYMMETRIC_GENERIC);

loadAlgorithms(SYMMETRIC_PACKAGE,SYMMETRIC_MACS);

loadAlgorithms(SYMMETRIC_PACKAGE,SYMMETRIC_CIPHERS);

loadAlgorithms(ASYMMETRIC_PACKAGE,ASYMMETRIC_GENERIC);

loadAlgorithms(ASYMMETRIC_PACKAGE,ASYMMETRIC_CIPHERS);

loadAlgorithms(KEYSTORE_PACKAGE,KEYSTORES);

loadAlgorithms(SECURE_RANDOM_PACKAGE,SECURE_RANDOMS);

loadPQCKeys();//sowecanhandlecertificatescontainingthem.
//省略。。。
}

正是由于这些算法实现的加载,导致MD5.create()第一次调用时耗时超过数十秒。

好了,既然找到了问题。那么改动起来就很简单了,小编尝试寻找了糊涂包中提供的方法,发现并没有入参可以关闭该三方加密包的初始化。于是换用了Google提供的MD5的实现。重新打包,部署,一次成功,完美。

后语

QA同学在测试环境测出了这个问题,而自信的本人不屑一顾,坚持自己愚昧的观点,先认为是Mock的问题,接着又说是网关的问题。由于我的盲目自信,导致上线到很晚,表示非常的惭愧。总结失败的原因:

32d84f10-19aa-11ee-962d-dac502259ad0.png
  • 合理评估使用第三方包
  • 测试环境遇到的问题尽力去追,不要盲目下结论
  • 要听QA的话


声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 数据
    +关注

    关注

    8

    文章

    6867

    浏览量

    88800
  • md5
    md5
    +关注

    关注

    0

    文章

    28

    浏览量

    20855
  • Check
    +关注

    关注

    0

    文章

    4

    浏览量

    7549

原文标题:震惊,一行MD5居然让小伙伴都回不了家!!!

文章出处:【微信号:magedu-Linux,微信公众号:马哥Linux运维】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    【安全算法之MD5MD5摘要运算的C语言源码实现

    【安全算法之MD5MD5摘要运算的C语言源码实现
    的头像 发表于 09-12 16:32 3538次阅读
    【安全算法之<b class='flag-5'>MD5</b>】<b class='flag-5'>MD5</b>摘要运算的C语言源码实现

    不知道有没有用PADS 9.5的小伙伴,我安装了破解不了喔。

    不知道有没有用PADS 9.5的小伙伴,我安装了破解不了喔。求解
    发表于 12-19 23:07

    植物小伙伴

    互联网上通知我的手机。植物小伙伴基站的设计。左上:内部框架结构。中间:侧板连接到框架结构。右上角:LED照明灯试验基地。LED灯的底部被盖上了层半透明的丙烯酸。这允许光散射在丙烯酸和散射光在基地。基站
    发表于 09-16 17:14

    【云智易申请】办公桌上的智能小伙伴

    申请理由:我的项目“办公桌上的智能小伙伴”已入围2015中国硬件大赛,其中重要技术Wifi的接入是关键,想通过贵公司的开发板学习下。项目描述:1.本产品是基于建立智能办工桌的思路进行研发的
    发表于 08-15 01:10

    【MiCOKit申请】办公桌上的智能小伙伴

    申请理由:我的项目“办公桌上的智能小伙伴”已入围2015中国硬件大赛,其中重要技术Wifi的接入是关键,想通过贵公司的开发板学习下.项目描述:1.本产品是基于建立智能办工桌的思路进行研发的
    发表于 08-19 09:59

    MD5计算hex文件的过程是什么

    大家好, 是否可以在SPC工作室中计算Hex文件或elf的MD5校验和,如果是,请告诉我计算MD5的过程。 提前致谢, ---谢谢&amp;问候,Mujeeb以上来自于谷歌翻译以下为原文 Hi
    发表于 02-13 08:35

    C#教程之MD5加密

    C#教程之MD5加密,很好的C#资料,快来学习吧。
    发表于 04-20 15:27 14次下载

    labview md5加密算法.llb

    md5加密算法 md5加密算法 md5加密算法 md5加密算法
    发表于 05-25 14:25 111次下载

    md5算法原理与实现

    MD5为计算机安全领域广泛使用的种散列函数,用以提供消息的完整性保护。用于确保信息传输完整致。是计算机广泛使用的杂凑算法之,主流编程语言普遍已有
    发表于 12-28 08:42 7105次阅读
    <b class='flag-5'>md5</b>算法原理与实现

    MD5算法硬件加速模型

    针对MD5软件实现方法存在占用资源大、安全性差等缺点,提出了基于NetMagic平台的MD5硬件加速模型设计方案,并基于ModelSim和NetMagic平台对提出的非流水线与流水线硬件加速模型进行
    发表于 01-12 16:45 0次下载
    <b class='flag-5'>MD5</b>算法硬件加速模型

    md5算法可逆吗_MD5值是什么

    MD5不可逆的原因是由于它是种散列函数(也叫哈希函数,哈希函数又称散列函数,杂凑函数,他是个单向密码体制,即从明文到密文的不可逆映射,只有加密过程没有解密过程,哈希函数可以将任意长度的输入经过
    的头像 发表于 11-16 15:30 1.3w次阅读

    md5是什么_md5怎么用

    MD5信息摘要算法(英语:MD5 Message-Digest Algorithm),种被广泛使用的密码散列函数,可以产生出个128位(16字节)的散列值(hash value),
    的头像 发表于 11-16 15:42 1.2w次阅读

    md5校验失败怎么解决

    英雄联盟更新包md5校验失败怎么办?将给大家介绍两种解决问题的方法,都是可以完美的解决更新包md5校验失败问题。第种不行就换第二种;第二种不行换第三种。
    的头像 发表于 11-16 15:50 3.9w次阅读

    Linux获取文件MD5码命令md5sum详解

    md5sum 用于计算和校验文件的MD5值。
    的头像 发表于 10-27 11:20 3296次阅读
    Linux获取文件<b class='flag-5'>MD5</b>码命令<b class='flag-5'>md5</b>sum详解

    Linux中文件MD5校验方法

    由于生成的md5信息中,每个md5值后都紧跟着对应的文件的路径(可能是相对路径),于是将生成的md5保存到某个文件中,以后可以使用该文件来检查md5值对应文件内容是否发生了修改。
    发表于 04-22 12:40 603次阅读