小白也能玩轉開源項目,你與大神只差這幾步!
原創【51CTO.com原創稿件】作為開發者,如果能充分利用好開源項目中的資源,不僅能提高實踐能力,專業知識水平,還能從中學到優秀的架構思想。
本文將提供一些學習開源項目的思路,相信看了這篇文章,小白也可學習讀懂開源項目,不必再對著高大上的開源項目望而生畏,淺嘗輒止。
學習的價值
總結起來,學習開源項目的價值主要包括以下幾點:
專業水平的提升
很多通用的專業知識,在專業領域內去到哪個公司都能通用,特別是底層方面的知識,可以在開源項目中學到,比如多線程處理、網絡通信、操作系統處理等。
舉個例子,通過學習 Redis 的 RDB 持久化模式的“會將當前內存中的數據庫快照保存到磁盤文件中”,可以學習到在操作系統 fork 一個子進程來實現,再繼續深入的話,就涉及到父子進程機制,copy-on-write 技術。
這些專業知識之間是可以聯系起來的并且像一顆大樹一樣自我生長,但是當沒理解透徹,自然沒法產生聯系,也就不能夠自我生長了。
當我們對開源項目的關鍵的點理解清晰,知識也隨著自我生長,也就如滾雪球一樣可以滾起來了。
解決問題能力的提升
通過學習開源項目的實現,出現線上問題時,可以快速定位問題癥結所在,通過修改配置或者修改源代碼來解決;或者當業務需求沒有合適的開源項目能滿足時,可以改造現有的開源項目來滿足業務。
作為要優秀開發,避免陷入“API 操作工”的被動局面,學習開源項目的一個很重要目的就是知道其功能點是如何實現且優化的。
學習其中的知識好比公式的推導過程,掌握基本 API 使用好比會數學公式可以應付考試。
但是理解好的推導過程根據有助于記憶和理解,知其然也要知其所以然,當遇那些沒法套公式的情況下,我們也知道如何解決。
思維的提升
通過學習成熟的開源項目的優秀架構,可以總結和理解一些軟件設計常用的架構思路。
例如實現高可用,主要是通過集群的數據冗余;例如 Kafka 集群,HDSF 集群,實現可擴展可以考慮把變化層和不變層隔離,把業務實現抽象化;例如 Spring 的預留的一些可擴展接口。
常見錯誤觀點
學習開源項目有一些常見的錯誤觀點,導致新手容易望而生畏而輕易放棄,或者浪費大量時間而收獲不大。
“學習開源項目是架構師,技術大牛的事,我作為新手根本難以學會,就算學了也用不到”
學習是一個過程,不是一朝一夕就可以成為大牛的,但是只要踏出第一步,總會有可能實現大牛夢想的。
另一方面,通過不斷復盤不斷總結,加以合適的方法論指導,相信是可以有所收獲,能力得到提升的。
學習之后對于邏輯思維,知識體系的構建相信會有很大提升,即使項目沒用到具體的開源項目,以后遇到相關問題可以觸類旁通,舉一反三,也是一種進步。
“數據結構和算法很重要,我只要學習這項目中的兩方面就可以了”
不要只盯著數據結構和算法,這兩點在開源項目中并沒有那么重要。
例如 Netty 中的超時隊列是基于紅黑樹來實現的,我們其實只需要知道這一點就夠了,除非需要改造這方面的功能。更重要的是理解系統的設計,功能的實現方案。
“一頭扎進源碼進行學習”
很多新手篤信社區論壇流行的一句話:“Talk is cheap,show me the code”,一頭扎進源碼閱讀,卻最后陷入源碼的泥潭中,在層層代碼函數跳轉中迷失了方向。
其實學習開源項目應該是自頂而下的,最底層的源碼應該是最后才開始學習,在此之前,需要學習項目相關架構設計方面的知識。
有了這些知識,就仿佛數據庫有了索引,按照知識索引來進行源碼針對性突破,如巡航導彈精準爆破,自然比地毯式轟炸更起到事半功倍的作用。
學習的四個層次
根據學習理解的深入程度不同,可以把學習分為 4 個層次,如上圖所示。
基礎學習
對項目有一個大概性、基礎性的了解,比如項目是什么,有什么作用,大概怎么用,解決了什么問題。
在面試中,不少初入職場的人的簡歷寫到用到眾多的技術框架,實際上往往僅僅只到了這個層次,再深入往下問,便支支吾吾答不上來了。
檢視學習
對項目有一個系統性的了解,系統的各方面功能,基本原理,優缺點,使用場景,各配置項、API 使用。
在實際工作中,如果作為一個團隊的普通成員,達到這個級別已經可以滿足基本業務開發需求,但是如果想有更高的技術追求,僅僅到此是不夠的。
分析學習
在檢視學習的基礎上,對開源項目的各項性能參數,各自場景性能調優有比較全面的了解和實踐經驗。
到達這個層次,在項目生產中,已經有獨當一面的能力,有一定能力承擔核心主力開發的角色。
主題學習
在分析學習的基礎上,對開源項目的關鍵功能模塊的源碼有所了解,能夠根據實際需要封裝、修改源碼,或者借鑒項目造出新的輪子。
到達這個層次,往往有一定能力承擔技術負責人、技術帶頭人的角色。
學習的四個步驟
針對上面提到的學習的層次,下面介紹如何“自頂而下”學習,來達到這 4 個層次。
步驟 1:基礎性了解學習
目標是達到基礎學習的層次,對項目有大概性的了解,包括項目背景,解決的問題場景,項目功能,使用場景,基本的 API 使用。通過查找官方文檔、相關博客、視頻資料學習即可。
通過對系統有大概性了解之后,會自然而然有一些疑問,例如實現的原理,優缺點等,后續學習帶著這些疑問進行學習會更高效。
步驟 2:系統性學習與實踐
目標是達到檢視學習的層次,對項目有系統性、全面性的了解,包括項目的功能、組成模塊、基本原理、使用場景、配置項、API 使用、與其他類似項目的優缺點比較等。方法步驟如下:
安裝運行
按照相關文檔,安裝運行項目。在這個過程中,需要關注:
- 系統的依賴組件,因為依賴組件是系統設計和實現的基礎,可以了解系統一下關鍵信息。
例如 Memcached 最重要的依賴是高性能的網絡庫 libevent,我們就能大概推測 Memcached 的網絡實現應該是 Reactor 模型的。
- 安裝目錄,常見的安裝目錄是 conf 存放配置文件,logs 存放日志文件,bin 存放日志文件。
而不同項目有些特殊目錄,比如 Nginx 有 HTML 目錄,這種目錄能促使我們帶著相關疑問繼續去研究學習,帶著問題去學習效率是最高的。
- 系統提供的工具,需要特別“關注命令行和配置文件”,它們提供 2 個非常重要的關鍵信息,系統具備哪些能力和系統將會如何運行。這些信息是我們學習系統內部機制和原理的一個觀察窗口。
通常情況下,如果對每個命令行參數和配置項的作用和原理基本掌握了解的話,基本上對系統已經很熟悉了。實踐中,可以不斷嘗試去修改配置項,然后觀察系統有什么變化。
系統性研究原理與特性
這點相當重要,因為只有清楚掌握技術的原理特性,才能算真正掌握這門技術,才能做架構設計的時候做出合理的選擇。
在這個過程中,需要重點關注:
- 關鍵特性的基本實現原理,關鍵特性是該開源項目流行的重要賣點,常見的有高性能、高可用、可擴展等特性,項目是如何做到的,這是我們需要重點關注的地方。
- 優缺點比對分析,優缺點主要通過對比來分析,即:我們將兩個類似的系統進行對比,看看它們的實現差異,以及不同的實現優缺點都是什么。
典型的對比有 Memcached 和 Redis、Kafka 和 ActiveMQ、RocketMQ的比較。
- 使用場景,項目在哪些場景適用,哪些場景不適用,業界適用的常見案例等。
在此階段可以通過學習官方技術設計文檔,架構圖,原理圖,或者相關技術博客,通常比較熱門的開源項目都有很多分析文檔,我們可以站在前人的基礎上避免重復投入。
但需要注意的是,由于經驗、水平、關注點、使用的版本不同等差異,不同的人分析的結論可能有差異,甚至有的是錯誤的,因此不能完全參照。
一個比較好的方式就是多方對照,也就是說看很多篇分析文檔,比較它們的內容共同點和差異點。
同時,如果有些技術點難以查到資料,自己又不確定,可以通過寫 Example 進行驗證,通過日志打印、調試、監測工具觀察理解具體的細節。
例如可以寫一個簡單程序使用 Netty,通過抓包工具觀察網絡包來理解其中的實現。
步驟 3:系統測試
如果只是自己學習和研究,可以參考網上測試和分析的文檔,但是如果要在生產環境投入使用必須進行測試。
因為網上搜的測試結果,不一定與自己的業務場景很契合,如果簡單參考別人的測試結果,很可能會得出錯誤的結論,或者使用的版本不同,測試結果差異也比較大。
要特別注意的是,測試必須建立在對這個開源項目有“系統性”了解的基礎上,不能安裝完就立馬測試。
否則可能會因為配置項不對,使用方法不當,導致沒有根據業務的特點搭建正確的環境、沒有設計合理的測試用例,從而使得最終的測試結果得出了錯誤結論,誤導了設計決策。
下面提供測試常見的思路參考,需要根據具體項目具體業務進行測試用例的設計:
核對每個配置項的作用和影響,識別出關鍵配置項。
進行多種場景的性能測試。
進行壓力測試,連續跑幾天,觀察 CPU、內存、磁盤 IO 等指標波動。
進行故障測試:Kill,斷電、拔網線、重啟 100 次以上、倒換等。
步驟 4:關鍵源碼學習
鉆研、領悟該項目的各種設計思想與代碼實現細節,基本定位是“精通”,精益求精,學無止境。這是大神們追求的境界。
如果希望成為團隊技術擔當、項目社區的重要貢獻者,則應當以這個層次作為努力的目標。
代碼不僅是讀,還要理和試,有的人連 API 都沒有調用過,上來就看代碼,以為省了時間,實際是邁向自我摧殘。
對源碼進行理和試的關鍵如下:
在 IDE 拿到調用棧
在 IDE 里讀。IDE 里可以方便跳轉,查看定義,比起網頁上看效率高得多。
通過 IDE 工具,運行 Example 程序進行跟蹤調試,通過打斷點可以得到程序運行的調用棧。盡可能編譯調試。能調試的代碼,幾乎沒有看不懂的。
把調用棧畫下來
把代碼的調用邏輯梳理出來之后,再通過畫圖工具,把代碼的圖畫出來,可以畫:流程圖、類圖、調用圖、時序圖,根據實際情況選擇最有表現力的圖。
此外,平時多了解一些設計模式。這樣看到名字里有 Proxy、Builder、Factory 之類的,就心領神會了。
橫向分層,縱向分塊。代碼都是分模塊的,有的是 core,有的是 util,parser 之類的,要知道看的是哪一層,那一塊。
有的小項目分層不明顯,也不必強求。要看的不只是語法上的技巧,更重要的是設計上的思路和原理。
讀沒讀懂,最簡單的標準是,假如給充足的時間,有沒有信心寫出一個差不多的東西來。
步驟總結
實際實踐操作中,完整執行上面 5 個步驟花費時間就長,通常情況下,前面 2 個步驟,在研究開源項目的時候都必不可少。
第 3 個步驟可以在工作中打算采用開源項目才實施,第 4 個步驟在有一定的時間和精力下靈活安排時間做。
與其每個項目走馬觀花去簡單了解,不如集中火力把一個項目研究吃透,即使半年才吃透一個,積累幾年之后數量還是很可觀的。
而且很多項目的思想是共同的,例如高可用方案、分布式協議等,研究透一個,再研究類似項目,你會發現學習速度非常快,因為已經把共性的部分掌握了,只需要再研究新項目差異的部分。
同時,在學習的過程中,需要不斷總結,復盤,輸出學習筆記,一方面鍛煉邏輯思維能力;一方面有利于建立知識索引,過一段時間回顧的時候通過索引可以快速重新掌握知識,不容易遺忘。
參考資料:
【51CTO原創稿件,合作站點轉載請注明原文作者和出處為51CTO.com】