這是why技術的第 91 篇原創文章git
這篇文章其實並無什麼技術性的分享,從個人角度而言,更可能是記錄和思考。github
把我對於源碼和以前寫的部分文章反哺給個人一些東西,帶來的一點點思考分享給你們。web
我很長時間沒打開個人 Outlook 郵箱了。算法
前兩天打開的時候發現我以前給 Dubbo 提交的 pr 竟然已經被合併到 master 了:apache
這是第一次,我提交的 pr 被合併了。緩存
這個 pr 是修復 LFU 緩存策略在 Dubbo 中即便配置了,也不起做用的 bug。負載均衡
因而我也算是爲開源項目貢獻過源碼的人了。框架
什麼你問我貢獻了多少代碼?編輯器
一行,是的,就一行!ide
並且,提及來,此次提交真的是沒有什麼技術含量的事情。由於這是一個必現的 bug,只是不多有人用到這個功能而已。
你知道的,當一個 bug 能穩定復現的時候,其實它已經就不算是一個 bug 了。
可是我想聊聊此次提交背後的一些東西。
從宿命論的角度來講,當我寫下面這篇文章的第一個字的時候,這個 bug 就註定是等着我去發現並修復了:
而這篇文章我敲下第一個字的時間是 2020 年 12 月的下旬,這是我 2020 年的最後一篇技術原創文章。
當我寫 LRU 的時候,我就知道 LFU 確定也是須要專門寫一篇的。
因而 2021 年的第一篇技術原創文章,我就選題了 LFU。
產生了這篇文章:
寫這篇文章的時候,我想起以前看 Dubbo 的版本,好像是提到了一下 LFU。
因而我翻到了 2.7.7 版本的發佈內容:
果真是支持了 LFU 緩存策略,因而翻出了提交的代碼記錄:
雖然他的實現邏輯沒有問題,Test 類也跑過去了。
可是絕不誇張的說,我看了一眼這個提交記錄,就發現了這裏勢必是有問題的。
他僅僅是把 LFU 緩存策略集合到了 Dubbo 代碼中,可是卻沒有給使用者提供使用的入口。
由於這裏是基於 SPI 實現的,他沒有在對應的配置文件中加入配置。
這個問題很是容易驗證,咱們能夠看一下。
其源碼的位置是:org.apache.dubbo.common.utils.LFUCache
源碼裏面告訴我這樣配置一下就可使用 LFU 的緩存策略:
可是,當我這樣配置,發起調用以後,是這樣的:
能夠看到當前請求的緩存策略確實是 lfu。
可是會拋出一個錯誤:
No such extension org.apache.dubbo.cache.CacheFactory by name lfu
沒有 lfu 這個策略。
這不是玩我嗎?
再看一下具體的緣由:
在 org.apache.dubbo.common.extension.ExtensionLoader#getExtensionClasses
處只獲取到了 4 個緩存策略,並無咱們想要的 LFU。
因此,在這裏拋出了異常:
爲何沒有找到咱們想要的 LFU 呢?
那就得看你熟不熟悉 SPI 了。
在 SPI 文件中,確實沒有 LFU 的配置:
因此,這是個 Bug,而這個 Bug 的解決方案,就是在 SPI 文件裏面加上一行 LFU 的配置便可。
通過上面的分析,其實你也發現了,這個並非一個有什麼技術含量的提交。
更多的是運氣成分。
只是因爲對於 Dubbo 框架有些許的瞭解,因此對於這個地方,我發現問題、定位問題、解決問題的速度很是的快。
這是運氣帶不給個人東西。
這須要日復一日的潛入到框架中去,去感覺它的脈絡,梳理它的結構,學習它的思想。
這是須要時間去沉澱和學習的東西。
注意,我說的是「潛入」,而非是流於表面的。
什麼是流於表面的呢?
好比,若是你以前沒有用過 Dubbo 框架,但你又想去了解,學習它。
因而你看到了個人這篇或者其餘的和 Dubbo 相關的公衆號文章,企圖從這些文章中入手。
記住魯迅先生的話:
亦或者是你在搜索框裏面,輸入 「Dubbo」,而後漫無目的的看了起來。
哪怕你買了一本 Dubbo 相關的書或者看了 Dubbo 相關的系列視頻,進行系統的學習。
我以爲,只要沒有本身親手去作,都屬於流於表面。
而本身動手的第一步,就是搭建 Demo,從 Demo 入手。
到後面高階一點的就是你瞭解到了這個框架的前世此生,能在幾個大版本之間進行橫向對比,知道爲何升級、怎麼升級、升級以後是怎麼樣的。
再以後,能細緻到某一個大的模塊的演變是怎樣的,歷史上出現過哪些 Bug,是怎麼去修復的。在那個版本以後進行了修復,是穩定的。
再舉個例子吧。
回到最開始的地方,我爲何會在寫 LFU 的時候聯想到 Dubbo 呢?
由於在 2.7.7 這個版本發佈的時候,我就關注到了它。
而當時關注到它的緣由並非 LFU ,而是新增了一種負載均衡策略:
因而我把以前的文章進行了彙總,寫下了這篇文章:
而其中一致性哈希負載均衡策略,我在實踐的時候也發現了一個 bug。
其實這個 bug 也是一個必現的 bug,爲何沒有被爆出來的緣由,我想是由於當前的版本使用的人很少,而使用一致性哈希負載均衡策略的就更少了,甚至沒有。
這個 bug 具體是這樣的:
https://github.com/apache/dubbo/issues/5429
我已經知道了在一致性哈希算法中的這行代碼就是致使 bug 的緣由:
System.identityHashCode(invokers)
甚至我也知道了,這行代碼致使 bug 的緣由是 invokers 這個集合的地址變了。
這個集合裏面,放的就是服務提供者列表。
集合裏面的服務者列表其實並無變化,只是每次都用了一個新的 list 來裝這些服務提供者。
而爲何每次都用一個新的 list 來裝,我也找到了:
問題就出在 TagRouter 中:
org.apache.dubbo.rpc.cluster.router.tag.TagRouter#filterInvoker
基本上到這裏,也就明確緣由了。
可是我前面說了,更高一級的是瞭解這個框架的前世此生。
問題出在 TagRouter,那麼這個 TagRouter 怎麼來的呢?
若是瞭解 Dubbo 2.7.x 版本新特性的朋友可能知道,標籤路由是 Dubbo2.7 引入的新功能。
巧就巧在我還真的清楚這個地方的前因後果。
由於個人第一篇技術文章就是寫的 Dubbo 2.7 新特性,當時進行了一個瞭解。
沒想到一年多之後,居然還呼應上了。
而這個 bug,其實也是一行代碼就能修復;
而我當時爲何沒有去修復呢?
由於最開始找到這個 bug 的時候,我想到的解決方案是寫個工具類。
思路也是隻關心 List 裏面的元素,而不關心 List 這個容器,可是實現方式比較複雜,改動點較多,還須要寫一個工具類。
當時就沒動手,想着先提個 issue 放着,有時間了再弄。
結果,沒想到 issue 放上去的當天就有人回覆並了一個我沒有想到的解決方案:
看到這個回覆的時候,我才一下回過神來,原來一行代碼就能代替我寫的工具類了啊。
而對於其中涉及到的知識點,我是知道的。
我反思了一下本身爲何沒有想到這個方案。
其實就是對於已知道的知識點,掌握不夠深入致使的,沒有達到融會貫通的地步。
知其然,也知其因此然,惋惜在須要使用的場景稍稍一變的狀況下,就想不起來了。
知道知識點,可是該用的時候卻記不起來,這種狀況其實挺常見的,那怎麼解決呢?
因而我寫下了這篇文章:
這篇文章就是個人解決方案,記錄下來嘛。
就像高中的時候人手一本的錯題本,作錯的題,不會的題都抄下來嘛。沒事的時候翻一翻,總有下次碰到的時候。再次碰到時,就是「一雪前恥」的機會。
我以前還寫過同樣的一篇文章:
當時這個版本推出以後,我就趕忙去研究了一下對應部分的源碼,而後寫下這篇自稱爲全網第一篇解析 Dubbo 2.7.5 里程碑版本中的改進點之一:客戶端線程模型優化的文章。
可是前兩天我看提交記錄的時候,發現了這樣的一個提交:
並找到了對應的 issue:
https://github.com/apache/dubbo/issues/7054
根據這個 issue,我去看了一下對應的源碼,確實是存在他描述的問題。
因而我就在想,我當時寫文章的時候也是深刻到源碼裏面了呀,爲何沒有發現這樣的問題呢?
我想緣由仍是在於本身當時思考的深度不夠,僅僅是搭建了一個很是簡陋的 Demo,並且把心思聚焦到了先後版本差別對比上。
只是摸到了一個大概的樣子,被源碼牽着走了,並無跳出源碼的包圍,帶着質疑的眼光去審視它。
因此,對於這種比較深層次的、一環扣一環的問題,本身仍是流於表面了一些。
前面舉了三個例子,一個是發現並解決了 bug,一個是僅發現未解決的 bug,一個是有 bug 但沒有發現。
前兩個 bug 都有一個共性,在簡單的 Demo 下就是必現的,只要跑到了對應的地方,就會出現和預期不符的狀況,比較容易發現。
最後一個 bug 隱藏的比較深刻一點,也許你觸發了,可是程序自愈了。
當有一天我能發現並解決這樣的 bug 時,我就不會說這是運氣了。
可是發現這些 bug 的前提是得動手搭建 Demo 呀。
你不看源碼,只是看網上的文章,是永遠發現不了問題的,也是潛入不進去的。
分享一下我看源碼的方法吧。
咱們知道開源框架的設計和理念大可能是很是優秀的,可是源碼裏面的細枝末節特別的多,一不當心就容易在源碼裏面迷失,直接就是一波勸退。
因此,對於初讀源碼的同窗,首先要作的就是把核心流程梳理出來,邊梳理邊畫圖,要多畫圖,別怕麻煩。
對於幾處關鍵的源碼,必定要寫上本身的備註。由於你知道的,當時也許你對這個地方爲何這樣寫門清,可是隔段時間再回來看,就摸不着頭腦了。這個時候,備註就顯的很是重要了。
對於看不明白的地方,打斷點,瘋狂的調試,反覆的調試。
等待主流程摸清楚以後,再去進入到源碼的細節部分。
舉個簡單的例子,好比你看 Dubbo 源碼,先摸清楚它一次請求大概的調用鏈路以後,再去細緻瞭解其中負載均衡的部分。
而後,就是多複習,多鞏固了。
你發現沒有,我說的這些其實你也知道,或者其餘人也是這樣說的。
爲何你看的時候就總是看不進去呢?不得要領呢?
是的,我開始也是這樣的。可是,無它,惟反覆練習爾。
共勉之。
才疏學淺,不免會有紕漏,若是你發現了錯誤的地方,能夠在後臺提出來,我對其加以修改。
感謝您的閱讀,我堅持原創,十分歡迎並感謝您的關注。