<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Fastjson已進(jìn)入公司黑名單組件庫(kù),新項(xiàng)目不準(zhǔn)使用~

          共 6586字,需瀏覽 14分鐘

           ·

          2024-05-27 13:02

          這個(gè)略顯馬麗蘇的標(biāo)題,各位看官將就著看吧。主要是怕被噴。fastjson真的很好,我用不用我喜不喜歡的,太不重要了,我只是覺得不適合我而已。

          話說以前GSON用得好好的,同事極力推薦我使用Fastjson,說很快云云。盡管我們的系統(tǒng)根本感知不出來(lái)這點(diǎn)速度差異。

          之前也聽說Fastjson爆出來(lái)什么重大漏洞,但對(duì)我們基本沒什么影響,所以這一點(diǎn)倒是沒什么偏見。

          然后在一個(gè)新項(xiàng)目上,腦抽抽,把gson換成了fastjson,還把spring boot默認(rèn)支持的jackson換成了fastjson。

          然后就開始遇到了一些問題。先聲明,這真不是尬黑,為了文章效果,故意網(wǎng)上扒些黑料拼湊起來(lái),本文所提到的問題,都來(lái)源于本人最近項(xiàng)目的真實(shí)經(jīng)歷。

          dateformat優(yōu)先級(jí)

          本來(lái)是一個(gè)風(fēng)和日麗的下午,一個(gè)非常簡(jiǎn)單的改動(dòng)需求。接口返回的時(shí)間只需要年月日日期類型不需要時(shí)分秒。

          因?yàn)槲遗渲萌謺r(shí)間格式化為yyyy-MM-dd HH:mmss,于是我愉快的在javabean的屬性上加了個(gè)注解。

          @JSONField(format="yyyy-MM-dd")

          本地測(cè)試一下,沒問題,提交到測(cè)試環(huán)境,搞定,完美。

          然后就接到產(chǎn)品的疑問,改動(dòng)呢?

          我登上去看了一下,唉,沒改到啊,日期還是帶了時(shí)分秒。

          我大意了啊,這么小的改動(dòng),又是在測(cè)試環(huán)境,就沒加驗(yàn)證。

          那么現(xiàn)在的直接問題是:fastjson關(guān)于時(shí)間配置在局部的配置沒有生效,使用的還是全局配置。

          現(xiàn)象是,開發(fā)環(huán)境windows上沒有問題,測(cè)試環(huán)境linux上出現(xiàn)了問題。兩者有什么區(qū)別呢?系統(tǒng)問題?

          既然懷疑是兩個(gè)系統(tǒng)導(dǎo)致的問題,那么就在idea里模擬一下linux系統(tǒng)。在VM options 添加 -Dos.name=linux

          這不能完全模擬linux系統(tǒng),只針對(duì)通過System.getproperty("os.name")來(lái)判斷當(dāng)前系統(tǒng)做某些操作的時(shí)候有用。

          通過這種方式?jīng)]復(fù)現(xiàn)。

          我又想到了遠(yuǎn)程調(diào)試。

          一陣操作猛如虎,遠(yuǎn)程調(diào)試倒是能進(jìn)斷點(diǎn),只是斷點(diǎn)進(jìn)不了第三方j(luò)ar包的源碼。等于白搞。

          得,還是回到源碼吧。拉下源碼,斷點(diǎn),觀察JSONSerializer類,主要是writeWithFormat方法。沒有發(fā)現(xiàn)問題。

          因?yàn)閼岩墒窍到y(tǒng)導(dǎo)致的,在源碼中搜索'linux''unix'關(guān)鍵字,沒有發(fā)現(xiàn)。斷點(diǎn)整個(gè)流程重點(diǎn)觀察了一下這部份也沒有發(fā)現(xiàn)問題。

          突然在JSONSerializer.dateFormatPattern上發(fā)現(xiàn)了這段注釋。

           

          這部份涉及到了調(diào)整dateformat的問題,重點(diǎn)在這個(gè)#1868,這通常是github的問題編號(hào)。

          1、 對(duì)于開源項(xiàng)目來(lái)說,解決了BUG,通常會(huì)把問題編號(hào)放到注釋里面去前提是注釋有必要通過問題編號(hào)可以看到問題的前因后果;
          2、 通常來(lái)說,對(duì)于github開源項(xiàng)目都有issue區(qū),拿著這個(gè)到編號(hào)直接到issue一搜就能搜到;
          3、 但也有一些項(xiàng)級(jí)項(xiàng)目,如spark,flink是沒有issue區(qū)的,它們的類型問題發(fā)現(xiàn)描述追蹤都使用jira平臺(tái);

          如:https://issues.apache.org/jira/browse/SPARK-38349%EF%BC%8C 在提交PR的時(shí)候標(biāo)題也嚴(yán)格按照[jira 編號(hào)][spark 子模塊(如core/sql) title]的規(guī)則來(lái)。

          所以拿著這個(gè)編號(hào)到issue區(qū),不管有沒有issue區(qū),也都可以直接到pullrequest區(qū)直接搜索,就算PR標(biāo)題里沒有問題編號(hào),PR描述肯定也是有的,只要是有嚴(yán)格PR流程的開源項(xiàng)目。

          所以這個(gè)問題在這里

          https://github.com/alibaba/fastjson/issues/1868

          相應(yīng)的PR在這里

          https://github.com/alibaba/fastjson/pull/2706

          通過ISSUES描述的已知信息,可以看出他遇到的問題跟我是一樣的,而這個(gè)問題早在2018年就提出了。但問題描述不太專業(yè),沒有涉及到環(huán)境以及最重要的fastjson的版本問題。

          而通過PR可知,這個(gè)問題最終在2020才解決,期間僅在ISSUES區(qū)提出的相同問題就有 #1868#1968 #2029 #24524個(gè)。

          解決問題的版本為:1.2.72.

          這個(gè)信息很關(guān)鍵。我對(duì)照了我開發(fā)環(huán)境的版本,是高于1.2.72的,所以沒有出現(xiàn)測(cè)試環(huán)境的問題。

          所以,柯南告訴我們,排除了所有可能性,剩下的哪怕再可笑,也是最終問題所在。

          那就是,測(cè)試環(huán)境所用的fastjson版本是低于1.2.72的。

          這種可能性是存在的,因?yàn)槲覀冇玫氖莔aven打代碼包,依賴包單獨(dú)存在。

          我最終在測(cè)試環(huán)境的依賴包目錄下發(fā)現(xiàn)了兩個(gè)Fastjson包,果然不出所料,有一個(gè)1.2.53的低版本,它就是罪魁禍?zhǔn)住?/p>

          所以,最終這個(gè)問題有相當(dāng)大的程度是由于我們團(tuán)隊(duì)自身問題引發(fā)的。但通過解決這個(gè)問題的過程也發(fā)現(xiàn)了一些有意思的情況。

          首先,F(xiàn)astjson在某一個(gè)版本為什么會(huì)引發(fā)這個(gè)問題。它肯定是某個(gè)PR改出問題的,rv,testcase覆蓋沒有到位。

          其次,從試圖解決這個(gè)問題的3個(gè)PR的時(shí)間線,分別在2018年,2019年,2020年。說明,fastjson這個(gè)項(xiàng)目的contributor看起來(lái)有百來(lái)人,但其中過于依賴其中某1個(gè)或者某些主力人員。精力有限,某些優(yōu)先級(jí)不那么高的BUG只能放任。

           

          同時(shí)這個(gè)項(xiàng)目的榮譽(yù)感并沒有那么高(或者叫并沒有那么吸引高手),它并不是apache頂級(jí)項(xiàng)目,要是其它諸如spark/flink、spring,哪怕是dubbo呢,很想象這些項(xiàng)目會(huì)有一個(gè)并不算復(fù)雜的BUG懸而未決長(zhǎng)達(dá)3年時(shí)間。在這些頂級(jí)開源項(xiàng)目,大家都是拼了老命的想找些BUG來(lái)提交PR。

          當(dāng)然,以上只是我個(gè)人的一點(diǎn)猜測(cè)。

          復(fù)盤,遇到Fastjson的問題,一開始就應(yīng)該奔著github的issues區(qū),它大概率已經(jīng)被前人踩坑了。

          $ref循環(huán)引用問題

          public ResultBody test () {
              List<Person> list = new ArrayList<>();
              Person obj1 = new Person("張三"48);
              list.add(obj1);

              Person obj2 = new Person("李四"23);
              list.add(obj2);

              Person obj3 = new Person("王麻子"17);
              list.add(obj3);

              List<Person> young = list.stream().filter(e -> e.getAge() <= 45).collect(Collectors.toList());
              List<Person> children =  list.stream().filter(e -> e.getAge()< 18).collect(Collectors.toList());

              HashMap map = new HashMap();
              map.put("young", young);
              map.put("children", children);

              return ResultBody.success(map);
          }

          以上測(cè)試接口返回前端什么?

          {
           "code":"200",
           "message":"成功!",
           "result":{
            "young":[
             {
              "age":23,
              "name":"李四"
             },
             {
              "age":17,
              "name":"王麻子"
             }
            ],
            "children":[
             {"$ref":"$.result.young[1]"}
            ]
           }
          }

          我現(xiàn)在并不知道什么循環(huán)引用檢測(cè),這時(shí)候它是我的知識(shí)盲區(qū)。

          此時(shí),我觀察到的現(xiàn)象是,young和children兩個(gè)list對(duì)象中均引用指向了王麻子這個(gè)對(duì)象。然后,在第2次children引用的時(shí)候它在序列化的時(shí)候直接指向了第1個(gè)young里相應(yīng)對(duì)象引用。

          當(dāng)然遇到這個(gè)問題的時(shí)候,我在仔細(xì)觀察排除了非fastjson的問題以后,這次我學(xué)聰明了,我直接來(lái)到了github的issues區(qū),搜索$ref。

           

          果然有很多同道中人,近150個(gè)問題,從時(shí)間上來(lái)看還挺新鮮。我點(diǎn)擊了closed,既然關(guān)閉了,那肯定解決了吧。

          我點(diǎn)進(jìn)了closed區(qū)第一個(gè)問題,然后作者讓升級(jí)到fastjson2。???

           

          如果我沒有理解錯(cuò),fastjson和fastjson2可不是兩個(gè)版本的區(qū)別,是兩個(gè)項(xiàng)目也!據(jù)說API也有兼容性問題。直接這樣升級(jí)過去,談何容易!

          我覺得這也是個(gè)槽點(diǎn),F(xiàn)astjson好像并沒有一個(gè)穩(wěn)定維護(hù)的版本,遇到問題總是在升級(jí),升級(jí)的過程中也沒做好質(zhì)量控制,又引入了新的問題。

          還是在當(dāng)前項(xiàng)目尋求解決方法吧,哪怕升版本也好啊。

          終于在另一個(gè)問題下面找到了問題所在以及解決方案。

          https://github.com/alibaba/fastjson/issues/3643

          我現(xiàn)在知道這是由于循環(huán)引用檢測(cè)引起的。通過設(shè)置SerializerFeature.DisableCircularReferenceDetect可以避免這個(gè)問題。

          但是,我的代碼其實(shí)并沒有循環(huán)引用啊,只是兩個(gè)子對(duì)象引用了同一個(gè)對(duì)象而已。這算什么?誤傷嗎?

          更重要的,一些控制權(quán)應(yīng)該在使用者手里?

          比如,當(dāng)前這個(gè)循環(huán)引用在序列化會(huì)出的問題,應(yīng)該是用戶手動(dòng)去開啟,而不是默認(rèn)給用戶開啟。

          在優(yōu)先級(jí)上,全局應(yīng)該關(guān)閉,在有循環(huán)引用的地方,讓用戶選擇局部開啟。

          現(xiàn)在我的前端并沒有使用Fastjson,面對(duì)"$ref":"$.result.young[1]"這種文本,它能解析嗎?它不能呀。我測(cè)試了一下,好像使用fastjson也并不能解析回來(lái):

           

          注:經(jīng)提醒,這里應(yīng)使用完整報(bào)文解析,經(jīng)測(cè)試,確實(shí)可以。感謝提醒!

          更可怕的問題是,剛好在測(cè)試環(huán)節(jié)有兩個(gè)子對(duì)象引用了同一個(gè)對(duì)象,被我提前發(fā)現(xiàn)了。如果測(cè)試環(huán)境沒有這樣的情況,在生產(chǎn)環(huán)境剛好遇到了呢?那就是生產(chǎn)事故了呀。

          本來(lái)是一個(gè)挺好的設(shè)計(jì)點(diǎn),能起到錦上添花的作用,但它卻可能暴雷,這是好心辦壞事。

          同樣的,還有SerializerFeature.WriteMapNullValue

          如果一個(gè)字段值為null,fastjson默認(rèn)就不返回該字段了。本來(lái)前后端約定好,如果為null就怎樣處理的邏輯,可能在生產(chǎn)環(huán)境中突然暴雷啊。

          就像WriteNullListAsEmpty就很好,不錯(cuò)的設(shè)計(jì)點(diǎn),如果返回的list為null的時(shí)候,用戶可以選擇讓它序列化為[],但它也不是默認(rèn)開啟的呀,給了用戶額外的選擇權(quán),對(duì)吧。

          總結(jié)

          寫到這里的時(shí)候,我是真心覺得fastjson有比競(jìng)品有些特色的地方。這真不是為了所謂的客觀公正,非要負(fù)面寫多點(diǎn),再搞點(diǎn)正面的。

          為了寫文章,那肯定要去試驗(yàn),得把競(jìng)品也拿出來(lái)測(cè)試一下,一測(cè)試發(fā)現(xiàn)并不是fastjson獨(dú)有的,尷尬!

          但我還是那句話,不管你信不信,對(duì)于開源項(xiàng)目,特別是這樣一個(gè)廣泛使用的開源項(xiàng)目,肯定有非常值得學(xué)習(xí)的地方。一個(gè)開源項(xiàng)目,如果整天拿著顯微鏡去觀察,那肯定能找出不少毛病。

          這里稍微總結(jié)一下本文的信息點(diǎn)。并不一定是某個(gè)具體BUG,而是通過這個(gè)BUG,解決這個(gè)BUG背后所展現(xiàn)出來(lái)的fastjson的信息或趨勢(shì)。

          1、 review、testcase覆蓋不是很到位;
          2、 contributor看起來(lái)很多,但嚴(yán)重依賴主力人員而主力精力有限,某些優(yōu)先級(jí)不那么高的BUG只能放任;
          3、 這個(gè)項(xiàng)目的榮譽(yù)感并沒有那么高,或者叫并沒有那么吸引高手);
          4、 有些功能點(diǎn)應(yīng)該把控制主動(dòng)權(quán)交給用戶,如DisableCircularReferenceDetect,WriteMapNullValue等默認(rèn)開啟非常容易導(dǎo)致線上暴雷;
          5、 作者已經(jīng)全面轉(zhuǎn)向fastjosn2,而且哪怕在這之前,對(duì)于fastjson沒有一個(gè)穩(wěn)定維護(hù)的版本,不斷升級(jí),不斷引入新問題;

          最后說一句,fastjson1已經(jīng)進(jìn)入公司黑名單組件庫(kù),新項(xiàng)目一律不準(zhǔn)使用~

           

          加小編微信,回復(fù) 40 白嫖40套 java/spring/kafka/redis/netty 教程/代碼/視頻 等


          掃二維碼,加我微信,回復(fù):40

           注意,不要亂回復(fù) 

          沒錯(cuò),不是機(jī)器人
          記得一定要等待,等待才有好東西

          瀏覽 333
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  青娱乐成人网 | 久久天天夜夜操夜色AV麻豆 | 青娱乐久久91 | 蜜桃操逼视频 | 在线观看一区二区视频 |