主頁 > 後端開發 > Fastjson 很快,但不適合我....

Fastjson 很快,但不適合我....

2023-05-26 15:32:26 後端開發

作者: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 #24524 個,

解決問題的版本為: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 回圈參考問題

以上測驗介面回傳前端什么?

我現在并不知道什么回圈參考檢測,這時候它是我的知識盲區,此時,我觀察到的現象是,youngchildren兩個 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 的資訊或趨勢,

  1. reviewtestcase 覆寫不是很到位
  2. contributor 看起來很多,但嚴重依賴主力人員,而主力精力有限,某些優先級不那么高的 BUG 只能放任,
  3. 這個專案的榮譽感并沒有那么高,或者叫并沒有那么吸引高手),
  4. 有些功能點應該把控制主動權交給用戶,如 DisableCircularReferenceDetectWriteMapNullValue 等,默認開啟非常容易導致線上暴雷,
  5. 作者已經全面轉向 fastjosn2,而且哪怕在這之前,對于 fastjson 沒有一個穩定維護的版本,不斷升級,不斷引入新問題,

祝愿 fastjson2 越來越好,不要步 struts2 的后塵,

近期熱文推薦:

1.1,000+ 道 Java面試題及答案整理(2022最新版)

2.勁爆!Java 協程要來了,,,

3.Spring Boot 2.x 教程,太全了!

4.別再寫滿屏的爆爆爆炸類了,試試裝飾器模式,這才是優雅的方式!!

5.《Java開發手冊(嵩山版)》最新發布,速速下載!

覺得不錯,別忘了隨手點贊+轉發哦!

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/553495.html

標籤:Java

上一篇:JavaWeb編程面試題——Spring Web MVC

下一篇:返回列表

標籤雲
其他(159759) Python(38169) JavaScript(25456) Java(18133) C(15231) 區塊鏈(8268) C#(7972) AI(7469) 爪哇(7425) MySQL(7213) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5873) 数组(5741) R(5409) Linux(5343) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4576) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2434) ASP.NET(2403) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) .NET技术(1977) 功能(1967) Web開發(1951) HtmlCss(1948) C++(1922) python-3.x(1918) 弹簧靴(1913) xml(1889) PostgreSQL(1878) .NETCore(1862) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 【C++】Microsoft C++、C 和匯編程式檔案

    ......

    uj5u.com 2020-09-10 00:57:23 more
  • 例外宣告

    相比于斷言適用于排除邏輯上不可能存在的狀態,例外通常是用于邏輯上可能發生的錯誤。 例外宣告 Item 1:當函式不可能拋出例外或不能接受拋出例外時,使用noexcept 理由 如果不打算拋出例外的話,程式就會認為無法處理這種錯誤,并且應當盡早終止,如此可以有效地阻止例外的傳播與擴散。 示例 //不可 ......

    uj5u.com 2020-09-10 00:57:27 more
  • Codeforces 1400E Clear the Multiset(貪心 + 分治)

    鏈接:https://codeforces.com/problemset/problem/1400/E 來源:Codeforces 思路:給你一個陣列,現在你可以進行兩種操作,操作1:將一段沒有 0 的區間進行減一的操作,操作2:將 i 位置上的元素歸零。最終問:將這個陣列的全部元素歸零后操作的最少 ......

    uj5u.com 2020-09-10 00:57:30 more
  • UVA11610 【Reverse Prime】

    本人看到此題沒有翻譯,就附帶了一個自己的翻譯版本 思考 這一題,它的第一個要求是找出所有 $7$ 位反向質數及其質因數的個數。 我們應該需要質數篩篩選1~$10^{7}$的所有數,這里就不慢慢介紹了。但是,重讀題,我們突然發現反向質數都是 $7$ 位,而將它反過來后的數字卻是 $6$ 位數,這就說明 ......

    uj5u.com 2020-09-10 00:57:36 more
  • 統計區間素數數量

    1 #pragma GCC optimize(2) 2 #include <bits/stdc++.h> 3 using namespace std; 4 bool isprime[1000000010]; 5 vector<int> prime; 6 inline int getlist(int ......

    uj5u.com 2020-09-10 00:57:47 more
  • C/C++編程筆記:C++中的 const 變數詳解,教你正確認識const用法

    1、C中的const 1、區域const變數存放在堆疊區中,會分配記憶體(也就是說可以通過地址間接修改變數的值)。測驗代碼如下: 運行結果: 2、全域const變數存放在只讀資料段(不能通過地址修改,會發生寫入錯誤), 默認為外部聯編,可以給其他源檔案使用(需要用extern關鍵字修飾) 運行結果: ......

    uj5u.com 2020-09-10 00:58:04 more
  • 【C++犯錯記錄】VS2019 MFC添加資源不懂如何修改資源宏ID

    1. 首先在資源視圖中,添加資源 2. 點擊新添加的資源,復制自動生成的ID 3. 在解決方案資源管理器中找到Resource.h檔案,編輯,使用整個專案搜索和替換的方式快速替換 宏宣告 4. Ctrl+Shift+F 全域搜索,點擊查找全部,然后逐個替換 5. 為什么使用搜索替換而不使用屬性視窗直 ......

    uj5u.com 2020-09-10 00:59:11 more
  • 【C++犯錯記錄】VS2019 MFC不懂的批量添加資源

    1. 打開資源頭檔案Resource.h,在其中預先定義好宏 ID(不清楚其實ID值應該設定多少,可以先新建一個相同的資源項,再在這個資源的ID值的基礎上遞增即可) 2. 在資源視圖中選中專案資源,按F7編輯資源檔案,按 ID 型別 相對路徑的形式添加 資源。(別忘了先把檔案拷貝到專案中的res檔案 ......

    uj5u.com 2020-09-10 01:00:19 more
  • C/C++編程筆記:關于C++的參考型別,專供新手入門使用

    今天要講的是C++中我最喜歡的一個用法——參考,也叫別名。 參考就是給一個變數名取一個變數名,方便我們間接地使用這個變數。我們可以給一個變數創建N個參考,這N + 1個變數共享了同一塊記憶體區域。(參考型別的變數會占用記憶體空間,占用的記憶體空間的大小和指標型別的大小是相同的。雖然參考是一個物件的別名,但 ......

    uj5u.com 2020-09-10 01:00:22 more
  • 【C/C++編程筆記】從頭開始學習C ++:初學者完整指南

    眾所周知,C ++的學習曲線陡峭,但是花時間學習這種語言將為您的職業帶來奇跡,并使您與其他開發人員區分開。您會更輕松地學習新語言,形成真正的解決問題的技能,并在編程的基礎上打下堅實的基礎。 C ++將幫助您養成良好的編程習慣(即清晰一致的編碼風格,在撰寫代碼時注釋代碼,并限制類內部的可見性),并且由 ......

    uj5u.com 2020-09-10 01:00:41 more
最新发布
  • Fastjson 很快,但不適合我....

    作者:nyingping\ 來源:juejin.cn/post/7215886869199863869 > 記者:大爺您有什么特長呀? > > FastJson:我很快。 > > 記者:23423 乘以 4534 等于多少? > > FastJson:等于 2343. > > 記者:?? > > F ......

    uj5u.com 2023-05-26 15:32:26 more
  • JavaWeb編程面試題——Spring Web MVC

    面試題==知識點,這里所記錄的面試題并不針對于面試者,而是將這些面試題作為技能知識點來看待。不以刷題進大廠為目的,而是以學習為目的。這里的知識點會持續更新,目錄也會隨時進行調整。 ......

    uj5u.com 2023-05-26 15:32:13 more
  • 聊聊「短信」渠道的設計與實作

    短信在實作的邏輯上,也遵循訊息中心的基礎設計,即訊息生產之后,通過訊息中心進行投遞和消費,屬于典型的生產消費模型; ......

    uj5u.com 2023-05-26 15:31:57 more
  • javaer你還在手寫分表分庫?來看看這個框架怎么做的 干貨滿滿

    # java orm框架easy-query分庫分表之分表 高并發三駕馬車:分庫分表、MQ、快取。今天給大家帶來的就是分庫分表的干貨解決方案,哪怕你不用我的框架也可以從中聽到不一樣的結局方案和實作。 一款支持自動分表分庫的orm框架[`easy-query`](https://github.com/ ......

    uj5u.com 2023-05-26 15:31:40 more
  • 【RocketMQ】NameServer總結

    NameServer是一個注冊中心,提供服務注冊和服務發現的功能。NameServer可以集群部署,集群中每個節點都是對等的關系(沒有像ZooKeeper那樣在集群中選舉出一個Master節點),節點之間互不通信。 **服務注冊** Broker啟動的時候會向所有的NameServer節點進行注冊, ......

    uj5u.com 2023-05-26 08:23:14 more
  • JVM系統引數

    JVM(Java虛擬機)是Java程式的運行環境,它可以通過一些系統引數進行配置和優化。以下是一些常用的JVM系統引數: 1. -Xmx: 用于設定JVM堆的最大記憶體大小。例如,-Xmx1g表示將堆的最大大小設定為1GB。 2. -Xms: 用于設定JVM堆的初始記憶體大小。例如,-Xms512m表示 ......

    uj5u.com 2023-05-26 08:23:06 more
  • 跟著hsp學springmvc--數字格式化介紹

    基本資料型別和字串型別的自動轉換<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %> <%@ page contentType="text/html;charset=UTF-8" language="j ......

    uj5u.com 2023-05-26 08:22:54 more
  • Python豎版大屏2 | 用pyecharts開發可視化的奇妙探索!

    [toc] 你好!我是[@馬哥python說](https://www.zhihu.com/people/13273183132),一名10年程式猿,正在試錯用pyecharts開發可視化大屏的非常規排版。 以下,我用8種ThemeType展示的同一個可視化資料大屏,可視化主題是分析**“淄博燒烤” ......

    uj5u.com 2023-05-26 08:22:28 more
  • 專案終于用上了 Spring 狀態機,非常優雅!

    來源:https://www.duidaima.com/Group/Topic/JAVA/11942 ## **1、什么是狀態機** ### 1.1 什么是狀態 先來解釋什么是“狀態”( State )。現實事物是有不同狀態的,例如一個自動門,就有 open 和 closed 兩種狀態。我們通常所說 ......

    uj5u.com 2023-05-26 08:22:11 more
  • Kotlin難點

    [toc] # 高階函式 高階函式是將函式用作引數或回傳值的函式,還可以把函式賦值給一個變數。 所有函式型別都有一個圓括號括起來的引數型別串列以及一個回傳型別:(A, B) -> C 表示接受型別分別為 A 與 B 兩個引數并回傳一個 C 型別值的函式型別。 引數型別串列可以為空,如 () -> A ......

    uj5u.com 2023-05-26 08:16:54 more