共计 4492 个字符,预计需要花费 12 分钟才能阅读完成。
作者:nyingping\
起源:juejin.cn/post/7215886869199863869
记者:大爷您有什么专长呀?
FastJson: 我很快。
记者:23423 乘以 4534 等于多少?
FastJson: 等于 2343.
记者:??
FastJson: 你就说快不快吧!
这个略显马丽苏的题目,各位看官将就着看吧。次要是怕被喷。FastJson 真的很好,我用不必我喜不喜欢的,太不重要了,我只是感觉不适宜我而已。
话说以前 Gson 用得好好的,共事极力推荐我应用 FastJson,说很快云云。只管咱们的零碎基本感知不进去这点速度差别。
之前也据说 FastJson 爆进去什么重大破绽,但对咱们根本没什么影响,所以这一点倒是没什么偏见。
而后在一个新我的项目上,脑抽抽,把 Gson 换成了 FastJson,Spring Boot 默认反对的 Jackson 换成了 FastJson。
而后就开始遇到了一些问题。先申明,这真不是尬黑,为了文章成果,成心网上扒些黑料拼凑起来,本文所提到的问题,都来源于自己最近我的项目的实在经验。
举荐一个开源收费的 Spring Boot 最全教程:
https://github.com/javastacks/spring-boot-best-practice
dateformat 优先级
原本是一个风和日丽的下午,一个非常简单的改变需要。接口返回的工夫只须要年月日日期类型不须要时分秒。因为我配置全局工夫格式化为yyyy-MM-dd HH:mmss
, 于是我欢快的在 javabean 的属性上加了个注解。
本地测试一下,没问题,提交到测试环境,搞定,完满。
而后就接到产品的疑难,改变呢?
我登上去看了一下,唉,没改到啊,日期还是带了时分秒。我粗心了啊,这么小的改变,又是在测试环境,就没加验证。
那么当初的间接问题是:FastJson 对于工夫配置在部分的配置没有失效,应用的还是全局配置。
景象是,开发环境 Windows 上没有问题,测试环境 Linux 上呈现了问题。两者有什么区别呢?零碎问题?
既然狐疑是两个零碎导致的问题,那么就在 idea 里模仿一下 linux 零碎。在 VM options 增加 -Dos.name=linux
这不能齐全模仿 linux 零碎,只针对通过
System.getproperty("os.name")
来判断以后零碎做某些操作的时候有用。
通过这种形式没复现,我又想到了近程调试。
一阵操作猛如虎,近程调试倒是能进断点,只是断点进不了第三方 jar 包的源码。等于白搞。
得,还是回到源码吧。拉下源码,断点,察看 JSONSerializer
类,次要是 writeWithFormat
办法。没有发现问题。
因为狐疑是零碎导致的,在源码中搜寻 ’linux”unix’ 关键字,没有发现。断点整个流程重点察看了一下这部份也没有发现问题。
忽然在 JSONSerializer.dateFormatPattern
上发现了这段正文。
这部份波及到了调整 dateformat 的问题,重点在这个#1868
, 这通常是 github 的问题编号。
1. 对于开源我的项目来说,解决了 BUG,通常会把问题编号放到正文外面去。前提是正文有必要。通过问题编号能够看到问题的前因后果。
2. 通常来说,对于 github 开源我的项目都有 issue 区,拿着这个到编号间接到 issue 一搜就能搜到。
3. 但也有一些项级我的项目,如 spark,flink 是没有 issue 区的,它们的类型问题发现形容追踪都应用 jira 平台。如:
https://issues.apache.org/jira/browse/SPARK-38349
在提交 PR 的时候题目也严格依照
[jira 编号][spark 子模块(如 core/sql) title]
的规定来。
所以拿着这个编号到 issue
区,不论有没有 issue
区,也都能够间接到 pullrequest
区间接搜寻,就算 PR 题目里没有问题编号,PR 形容必定也是有的,只有是有严格 PR 流程的开源我的项目。
所以这个问题在这里:
https://github.com/alibaba/fastjson/issues/1868
相应的 PR 在这里:
https://github.com/alibaba/fastjson/pull/2706
通过 ISSUES 形容的已知信息,能够看出他遇到的问题跟我是一样的,而这个问题早在 2018 年就提出了。但问题形容不太业余,没有波及到环境以及最重要的 FastJson 的版本问题。
而通过 PR 可知,这个问题最终在 2020 才解决,期间仅在 ISSUES 区提出的雷同问题就有 #1868 #1968 #2029 #2452
4 个。
解决问题的版本为:1.2.72.
这个信息很要害。我对照了我开发环境的版本,是高于 1.2.72 的,所以没有呈现测试环境的问题。
所以,柯南通知咱们,排除了所有可能性,剩下的哪怕再可笑,也是最终问题所在。
那就是,测试环境所用的 FastJson 版本是低于 1.2.72 的。
这种可能性是存在的,因为咱们用的是 maven 打代码包,依赖包独自存在。
我最终在测试环境的依赖包目录下发现了两个 Fastjson 包,果然不出所料,有一个 1.2.53 的低版本,它就是罪魁祸首。
所以,最终这个问题有相当大的水平是因为咱们团队本身问题引发的。但通过解决这个问题的过程也发现了一些有意思的状况。
首先,FastJson 在某一个版本为什么会引发这个问题。它必定是某个 PR 改出问题的,rv,testcase 笼罩没有到位。
其次,从试图解决这个问题的 3 个 PR 的工夫线,别离在 2018 年,2019 年,2020 年。阐明,FastJson 这个我的项目的 contributor 看起来有百来人,但其中过于依赖其中某 1 个或者某些主力人员。精力有限,某些优先级不那么高的 BUG 只能放任。
同时这个我的项目的荣誉感并没有那么高(或者叫并没有那么吸引高手),它并不是 Apache 顶级我的项目,要是其它诸如 Spark、Flink、Spring, 哪怕是 Dubbo 呢,很设想这些我的项目会有一个并不算简单的 BUG 悬而未决长达 3 年工夫。在这些顶级开源我的项目,大家都是拼了老命的想找些 BUG 来提交 PR。
当然,以上只是我集体的一点猜想。
复盘,遇到 FastJson 的问题,一开始就应该奔着 github 的 issues 区,它大概率曾经被前人踩坑了。
$ref 循环援用问题
以上测试接口返回前端什么?
我当初并不知道什么循环援用检测,这时候它是我的常识盲区。此时,我察看到的景象是,young
和 children
两个 list 对象中均援用指向了 王麻子
这个对象。而后,在第 2 次 children
援用的时候它在序列化的时候间接指向了第 1 个 young
里相应对象援用。当然遇到这个问题的时候,我在仔细观察排除了非 fastjson 的问题当前,这次我学聪慧了,我间接来到了 Github 的 issues 区,搜寻$ref
。
果然有很多同道中人,近 150 个问题,从工夫上来看还挺陈腐。我点击了 closed,既然敞开了,那必定解决了吧。
我点进了 closed 区第一个问题,而后作者让降级到 fastjson2。???
如果我没有了解错,FastJson 和 FastJson2 可不是两个版本的区别,是两个我的项目也!据说 API 也有兼容性问题。间接这样降级过来,谈何容易!
我感觉这也是个槽点,FastJson 如同并没有一个稳固保护的版本,遇到问题总是在降级,降级的过程中也没做好品质管制,又引入了新的问题。
还是在以后我的项目寻求解决办法吧,哪怕升版本也好啊。终于在另一个问题上面找到了问题所在以及解决方案。
https://github.com/alibaba/fastjson/issues/3643
我当初晓得这是因为循环援用检测引起的。通过设置 SerializerFeature.DisableCircularReferenceDetect
能够防止这个问题。
然而,我的代码其实并没有循环援用啊,只是两个子对象援用了同一个对象而已。这算什么?误伤吗?
更重要的,一些控制权应该在使用者手里?
比方,以后这个循环援用在序列化会出的问题,应该是用户手动去开启,而不是默认给用户开启。在优先级上,全局应该敞开,在有循环援用的中央,让用户抉择部分开启。
当初我的前端并没有应用 FastJson, 面对 "$ref":"$.result.young[1]"
这种文本,它能解析吗?它不能呀。
我测试了一下,如同应用 FastJson 也并不能解析回来:
注:经揭示,这里应应用残缺报文解析,经测试,的确能够。感激揭示!
更可怕的问题是,刚好在测试环节有两个子对象援用了同一个对象,被我提前发现了。如果测试环境没有这样的状况,在生产环境刚好遇到了呢?那就是生产事变了呀。
原本是一个挺好的设计点,能起到精益求精的作用,但它却可能暴雷,这是善意办好事。
同样的,还有 SerializerFeature.WriteMapNullValue
。如果一个字段值为null
,fastjson 默认就不返回该字段了。原本前后端约定好,如果为null
就怎么解决的逻辑,可能在生产环境中忽然暴雷啊。
就像 WriteNullListAsEmpty
就很好,不错的设计点,如果返回的 list 为 null
的时候,用户能够抉择让它序列化为[]
, 但它也不是默认开启的呀,给了用户额定的选择权,对吧。
总结
写到这里的时候,我是真心感觉 FastJson 有比竞品有些特色的中央。这真不是为了所谓的主观公正,非要负面写多点,再搞点侧面的。
为了写文章,那必定要去试验,得把竞品也拿进去测试一下,一测试发现并不是 FastJson 独有的,难堪!
但我还是那句话,不论你信不信,对于开源我的项目,特地是这样一个宽泛应用的开源我的项目,必定有十分值得学习的中央。一个开源我的项目,如果终日拿着显微镜去察看,那必定能找出不少故障。
这里略微总结一下本文的信息点。并不一定是某个具体 BUG, 而是通过这个 BUG,解决这个 BUG 背地所展示进去的 FastJson 的信息或趋势。
review
,testcase
笼罩不是很到位contributor
看起来很多,但重大依赖主力人员。而主力精力有限,某些优先级不那么高的 BUG 只能放任。- 这个我的项目的荣誉感并没有那么高,或者叫并没有那么吸引高手)。
- 有些性能点应该把管制主动权交给用户,如
DisableCircularReferenceDetect
,WriteMapNullValue
等。默认开启非常容易导致线上暴雷。- 作者曾经全面转向 fastjosn2,而且哪怕在这之前,对于 fastjson 没有一个稳固保护的版本,一直降级,一直引入新问题。
祝福 fastjson2 越来越好,不要步 struts2 的后尘。
近期热文举荐:
1.1,000+ 道 Java 面试题及答案整顿(2022 最新版)
2. 劲爆!Java 协程要来了。。。
3.Spring Boot 2.x 教程,太全了!
4. 别再写满屏的爆爆爆炸类了,试试装璜器模式,这才是优雅的形式!!
5.《Java 开发手册(嵩山版)》最新公布,速速下载!
感觉不错,别忘了顺手点赞 + 转发哦!