系統重構的道與術

amap_tech發表於2019-12-17

最近參與了很多重構專案,有以提高伺服器資源利用率為目標的Gateway閘道器、AMAPS等服務的重構,也有以提升架構合理性和研發效率為目標的共享業務服務化拆分,藉此機會把相關內容梳理一下,是分享更是自我總結和學習。準備以重構工作中容易產生誤區的地方或容易被忽視的重點來聊聊,既不重複網上千篇一律的各種方案資料,也對重構工作有參考價值。

什麼是“道和術”?個人簡單的理解,道就是思想,術是方法。可謂有道無術,術尚可求也;有術無道,止於術。分別從重構的基本思路和原則,以及常見重構方案的應用來分別講講系統重構的“道與術”。

一、系統重構之道

現在是進行重構的恰當時機嗎?重構前需要做什麼準備?如何保障重構工作順利完成並達成預期目標?從這幾個大家都關心的問題,來談談重構工作遵循的基本思路和原則。

從實際問題出發

“不能解決實際問題的重構就是耍流氓 ”,從實際問題出發,切勿為了重構而重構,看似簡單的道理,但現實中確實存在為了重構而發起的重構,或許是想應用誘人的新技術,或許是為了跟上流行趨勢,甚至有自己主動YY需求而發起的重構。作為工程師我們需要謹記系統穩定高於一切,任何重構都存在風險,沒有業務收益的重構相當於平白讓業務承擔非必要的風險,這是一種極不負責的表現。

所以,發起重構專案時,先想明白要解決什麼實際問題,是為了提升效能?還是加強安全?或是為了快速的持續整合和釋出?想明白再行動。

設定明確目標

目標是否明確很大程度上決定了事情的最終效果,重構專案也是如此。在組織管理、目標管理課程上經常會提及目標設定的SMART原則,同樣,重構專案也要有具體的、可衡量、可執行、可實現、且有時間限制的目標,可執行、可實現、且有時間限制這三者好理解,重點講講具體可衡量,上面提到的待解決問題可不可以作為重構專案的目標嗎?答案不可以,問題就出在具體可衡量上,就拿以解決效能問題的重構專案為例,目標應該是服務響應RT要降多少? 或是單核QPS承載量提升多少?甚至也可以是伺服器資源減少多少?這才是具體可衡量的目標。

那有些不好量化的目標怎麼做到可衡量呢?拿提升服務高可用性為目的的重構專案為例,目標確實不好量化,針對這樣的問題可以以具體事件為衡量標準,比如實現機房故障使用者無感知,或底層故障自動降級和恢復等 (系統高可用經常使用幾個9的指標來評定,但它是一個事後採集指標,用作指導中短週期專案目標並不適合)。

阿里內部經常會提到工作抓手,而這個具體可衡量的目標就是我們重構工作的抓手。

設計要有度

“設計不足”和“過度設計”一樣都是設計失誤,設計不足是因為缺乏必要的抽象思維和前瞻性思考,使得系統存在設計缺陷;而過度設計往往是對系統問題把脈不清,偏離實際需求過度追求擴充套件性而引入了多餘的設計,過度設計的結果並不只是並沒什麼用處的擴充套件功能,更多時候它會帶來一些新的問題,比如增加系統維護和迭代的成本、增加線上問題排查難度等等。

設計要有度除了設計不足和過度設計外,還有一個成本收益的層面需要考慮,可能有些設計的引入能解決一部分問題,但它方案過於複雜,實施成本過高,這時候就需要從收益產出比上去權衡是否要採納。

設計不足幾乎沒有捷徑,需要不斷的學習和經驗積累。而過度設計,需要我們在做設計方案時多想一想相關設計的必要性以及成本收益問題。

小步快走

提前做好迭代計劃是在重構工作中容易被忽略的重要事項,重構方案設計之初就要考慮如何分階段實施,甚至為了達到分階段目的有時需要在設計方案上做一些妥協。如果把重構比作建築施工,小步快走層層分離的策略就相當於搭建施工現場的腳手架,是一種把風險控制在可接受範圍的有效手段。

舉一個實際的重構經歷,是一個訂單服務,訂單量不大但業務種類很多(酒店、門票、火車票等等)。最終設計按訂單處理流程將系統劃分四個模組:下單模組、CP訂單同步模組、訂單處理模組、統計模組。有同學問過訂單量不大拆多個模組合適嗎?其實除了設計本身的考慮因素外,按訂單流程拆多個模組很重要的原因是為了能夠分階段上線和驗證,只有這樣風險才真正可控 (因一些特定原因沒按業務垂直拆分,這裡暫不詳表)。

所以系統重構儘可能採用迭代實施方案,而且是從一開始就要考慮。

二、系統重構之術

在系統重構工作中,會使用一些具體的手段來解決所面對的特定問題,在術的部分聊聊重構中經常使用的一些方案,方案的具體內容資料很多就不寫,我們這裡重點聊聊相關方案應用時要注意考慮哪些問題。

服務化

服務化在很多重構專案中被提及,抽象、解耦、分治、統一是系統設計和重構的重要思想,服務化是該思想的重要實踐,在運用服務化設計時,需要注意哪些問題?

服務化目標

做服務化設計或重構工作的時候,首先要想清楚服務化帶來的價值,它也是我們做服務化工作的目標。

需求層面:支援快速迭代

開發層面:程式碼解耦,獨立開發,降低維護成本

運維層面:獨立部署,單獨擴容,降級控制

上面提的是服務化帶來的價值,有意思的是,如果是一個不好的服務化設計,上面也會是服務化帶來的問題,比如經常有同學抱怨服務化設計比之前開發上線更麻煩了。所以清晰的認識服務化目標是服務化工作的第一步,如果目標沒有達成甚至帶來的是負面效果,就要重新審視相關設計是否合理了。

強調服務個體,弱通訊

在參與服務化工作的時候經常遇到同學上來就聊各種RPC框架或各種訊息中介軟體,服務化是一種服務設計模式或者說一種設計思想。服務化工作強調的是服務個體設計,具體的通訊方式至少在開始階段不是那麼重要。在不同階段儘量聚焦核心問題。

粒度選擇

服務化工作最難最依賴經驗的是服務粒度的選擇,如何結合系統實際特點正確定義子系統邊界,一方面有相關設計原則可以參照(比如單一原則、無狀態等等,網上資料很多),更多的還是經驗的積累,如果是系統重構工作,建議從優先順序重要的模組進行提煉,粒度可大可小不好把控時,可以考慮先實施較大粒度的方案,這樣即使有問題可以進一步最佳化拆分,但如果一下子過細導致過度設計,再想回去就比較難了。

高容錯性

前面提到服務化強調服務個體,而作為獨立的服務其容錯性設計應該是要被重點考慮的,它也決定了整個服務體系的穩定性。所以服務化不僅僅是把服務拆分出來,拆分後要分析各服務之間的依賴,區別強弱關係,進行相關容錯設計。

快取設計

如果說資料快取是重構工作中被使用最多的手段,估計不會有太大的歧義,使用資料快取方案以下幾點需要特別注意。

快取不是銀彈

涉及到效能最佳化經常會聽到“那我們加個快取”吧,確實資料快取對效能提升的效果立竿見影,幾乎成了很多同學在解決系統效能問題時條件反射式的選擇。

無論是新系統設計還是老系統重構,在面對效能問題時不要總把資料快取作為第一選擇,它會矇蔽你的眼睛,使你無法看到其他層面的問題。記得在之前一家企業軟體公司工作時,跟著公司首席架構師做基礎服務設計,他有一個要求就是系統初期設計不能考慮任何快取設計,這讓我印象深刻。效能提升就加快取,其實是在用戰 術上的勤奮掩蓋戰略上的懶惰,解決問題時我們需要多角度多維度的全面評估,這樣才有可能系統性的解決問題。

雪崩和穿透

資料快取解決了資料讀取效能問題,但同時也在系統架構裡引入了新的故障點。

雪崩和穿透是引入資料快取時需要考慮的問題。首先從業務層面要考慮相關情況下的降級策略和具體降級方案,從技術層面,快取自身的高可用、快取資料是否持久化、是否加入快取預熱機制、expire time否要進行離散設計等等這些細節都是要考慮的。

系統內部最佳化

程式碼重構

程式碼最佳化分為程式碼結構最佳化和程式碼內容最佳化,後者重點在於如何識別程式碼中的bad smell,有很多具體指導方法,這裡就不提了。而前者更多的是對程式碼設計的調整,考驗的是設計抽象能力,需要有較好的領域模型(DDD)知識。所以說一個好的程式設計師,他/她一定是個領域專家。

非同步化改造

對於IO密集型的應用,非同步化改造是很有效的手段,但實施起困難還是挺大的,體現在兩方面,一是要有完整技術解決方案的支援;幸運的是已經有同事給我們趟好了路,解決了公司常用中介軟體(Hsf、Tair、Metaq、Tddl、Sentinel等)非同步化的問題,給大家重點推薦淘寶架構升級專案相關資訊(羨慕無比,這種規模的重構可遇不可求),專案核心就是微服務化和基於響應式程式設計的非同步化改造,從中可見零起步做系統非同步化改造是多大的一個工程。另一方面是團隊自身學習成本,需要所有參與者對非同步化、響應式程式設計模型要有很好的認知,這點也尤其重要。

分庫分表

資料量級快速增長單庫無法滿足業務需求時,分庫分表是常用的應對方法。

如果是開發新系統,除非業務本身依賴海量資料,否則不建議在開發初期就實施分庫分表,因為這會在一定程度上加大系統設計和開發的難度。而且一開始就讓業務開發人員關切資料分庫分表,如果他經驗不足容易帶來額外的困惑,將原本簡單的問題處理複雜化。

關於主鍵生成策略,有不同機制供大家選擇,目前被使用和討論較多的是Snowflake,它有一個系統時間上的要求,另一個是Tddl的生成策略, 兼顧了效能、全域性唯一、單庫遞增的核心訴求。

分庫分表後需要考慮跨庫跨表查詢的問題,首先業務上要儘可能的避免,但像訂單業務就需要針對使用者、賣家進行不同維度的資料拆分(可考慮主庫從庫分別使用使用者、賣家作為分表鍵) 。如果是運營管理後臺類多條件的複雜查詢,不管是不是分庫分表,單庫同樣支援不好,非海量資料可以考慮使用ES,海量資料使用ES+HBASE。

三、說說系統評估

最後簡單的聊下系統評估,從研發角度,可以從高效能、高可用、可擴充套件性、可伸縮性、安全性、可運維性這六個維度來考量,沒有一個標尺,也不建議使用所謂的標準,系統評估結果一定是結合業務實際情況的結論,比如高可用,一個運營管理類平臺多例項部署可能就是良,但如果是線上交易系統,多機房只是起步要求。

做系統評估時結合業務實際情況,從上述六個維度分別按 嚴重缺失、不足、滿足 三檔進行評估,初步分析系統短板。另外特別需要注意的是,這些維度不是獨立存在的,在針對某一方面進行重構最佳化時,要深入考慮對系統其他層面的影響。

最後想說的是做好系統重構並不容易,其困難不在具體問題的解決上,它是一個系統性工程,如何能做到全面考量以及考慮多方面因素後選出相對最優解,才是最大的挑戰。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69941357/viewspace-2669015/,如需轉載,請註明出處,否則將追究法律責任。

相關文章