阿里畢玄:系統設計之解決核心問題的設計

簡介: 作者結合cases來講講解決核心問題的設計這個環節,回顧自己的cases,犯了不少的錯誤,也碰到了非常多複雜的權衡選擇的狀況,才逐漸更加明白一個架構師應該具備的一些能力。

作者:畢玄   文章來源:公衆號公衆號hellojavacases,涉及話題編程能力的高級進階、系統設計、技術方向、職業生涯的發展。

繼前面的系統建設的目的、可衡量的目標,達成目標的核心問題後,進入到解決核心問題的設計環節了,技術人員其實最擅長的是直奔這個主題,而且估計更期盼的也是這篇,有些時候會導致跳過前面的目的、目標環節,導致最終做出來的系統要麼沒貼合業務挑戰,要麼嘛偏離了做這個系統的初衷,所以我仍然強烈建議做系統設計的同學不要着急,一步一步來。

繼續結合自己的cases來講講解決核心問題的設計這個環節,回顧自己的cases,犯了不少的錯誤,也碰到了非常多複雜的權衡選擇的狀況,才逐漸更加明白一個架構師應該具備的一些能力。

HSF的設計

HSF在設計之初要解決的第一個核心問題就是做一個易用,能支撐每天上億次服務調用的服務方式的RPC框架。

易用這點在第一個版本犯了錯,不過還好是第一個版本,否則糾正錯誤的代價會無比巨大,那個版本里,如果要把一個spring的bean發佈爲HSF服務,或者調用一個HSF服務,需要寫一個文件,在文件裏描述發佈的服務和調用的服務,並且在這個文件放在jboss的某個目錄裏,這個方式看起來對在寫代碼的過程中完全沒有侵入,但導致的巨大問題是這文件放在哪裏寫,寫完後部署的階段怎麼自動放到對應的目錄去,在第二個版本里才把這個調整爲用一個Spring Bean的方式來做服務的發佈和調用,儘管這一定程度導致了業務代碼需要有對HSF的明顯的依賴,但對維護、部署等都變的很標準,所以從這裏可以看到,設計是全方位的,要考慮到的不僅僅是怎麼實現,還有別人怎麼用,運行、維護階段又是怎麼樣的。

HSF犯的第二個錯,就是在能支撐每天上億次服務調用的RPC框架這點上,是給我自己代碼生涯最大的教訓,甚至徹底改變了我之後做設計時的技術選型風格,在做HSF之前,我從來沒做過一天訪問量超過100w的系統,完全搞不清一個每天上億次的系統到底有什麼不同,HSF最早的版本在通訊框架上選擇了JBoss-Remoting,原因也其實比較簡單,因爲我們用的Web容器是JBoss,結果這個版本在一個非常重要的系統上線時,出現了嚴重的故障,導致了整個網站的響應速度都變的很慢,當時查了幾乎整整一天都沒查出原因到底是什麼,後來回滾恢復,所以可以肯定是HSF上線造成的,等到回滾後的一個星期內才查出原因,是因爲JBoss-Remoting在調用遠端時,默認的超時時間爲60s,而我們後端的那個系統在處理某些服務的時候會特別慢,進而導致了共用的處理線程池滿了,所以整個網站的表現就變慢了,這次問題讓我徹底明白了訪問量大的系統最重要的是對整個系統的處理過程要非常的清楚,因爲在訪問量大的情況下,一些小的問題有可能會放大成很大的問題,進而到故障,所以訪問量大的系統對技術的可控性要求是極高的,這也是最大的不同,可控性並不代表一定要完全自己寫,但要求如果用到開源的東西,要對開源的東西的代碼邏輯非常熟悉,爲了解決上面的問題,HSF基於Mina寫了一個自己版本的通訊框架,自己來處理連接方式、線程池等,後面在做各種HSF改造,以及其他技術改造時,基本都遵循了技術可控性這個原則。

在前面核心問題那篇裏也講到,HSF在設計時其實核心問題提煉的就是有問題的,導致了後面在負載均衡、服務化後問題排查這兩點上出現了嚴重的返工現象,而這些本其實都可以避免,就像現在再去做服務化框架的人基本都不會犯這樣的錯了。

在負載均衡這點上,在早期版本里,是通過硬件負載均衡設備來做的,這裏造成了好幾個問題,一是需要先配置要調用的服務的vip地址,當然,這可以通過一箇中央的配置服務器之類的方式,第二個是HSF採用的是長連接的方式,通過vip去連接後端的一個集羣時,這裏會出現非常麻煩的問題,例如後端集羣發佈重啓,很有可能就會造成連接的極度不均衡,進而導致故障。

除了上面兩個問題後,還有一個觸發HSF去做改造的原因是當時的硬件負載設備出現了流量跑滿的現象,而這是必須要經過的一個點,會造成全站全部崩潰,不希望在未來系統中有個這麼大的高風險的集中點,再加上上面的兩個問題,決定做徹底的改造,於是HSF開始設計了目前看起來在服務框架體系中非常經典的軟件方式的服務註冊、發現和尋址的結構。
image.png

在負載均衡這件事上,現在回顧也可以看出這個仍然是當初對一個訪問量巨大的系統考慮不夠全面造成的。

在服務化後會帶來的排查問題這點上,當初設計的時候更是完全沒有考慮到,導致了後面排查問題效率低、人力投入大等等問題,後來爲了解決這個問題,學習了Google家Dapper的思想,但花了很長時間這東西才真正落地。

除了上面這些外,HSF其實還有各種設計問題,例如最早的通訊協議裏竟然是沒有版本號的,導致後面升級時處理兼容的複雜,又例如更麻煩的一個話題就是在多語言支持上。

HSF作爲我第一個真正做的訪問量巨大且核心的系統的設計,由於當初的技術功底,犯下了無數錯誤,導致了N次返工、故障和彌補,當然也讓自己得到了很大的成長,這幾年回過頭想這個問題,越來越覺得必須無比感謝我當時的主管對我巨大的包容和支持,HSF的經歷,讓我在解決核心問題的設計這個環節上,明白的是作爲一個架構師,在技術選型上深厚的技術功底,在整個設計方案上知識的廣度,考慮的全面性(從開發態、部署態、運行態和運維態)都是要求極高的。

T4的設計

T4在覈心問題的提煉上沒有太大的問題,但在怎麼解這個問題的設計上那犯下的錯誤現在來看都是低級到不行。

爲了做到在一臺機器上能比以前用虛擬機的方式運行更多的應用進程,最早我們採用的方法是各種hack,其實要實現的就是進程級隔離,結果就是hack到了一定程度後,確實勉強能用了,但上線了一些小範圍,有了一些用戶後,發現我們的hack是很難枚舉的,非常痛苦,直到有一天“發現”了LXC,才走對了路線。

除了上面這個選型層面的問題外,T4的過程中還碰到過很多類似的問題,例如用什麼方法去控制磁盤空間的限制,最早我們也是用的同樣的image的方式,但image的方式對磁盤空間超賣其實是非常不友好的,後來爲了把這個方案更換成dir quota的方案,一幫人幾乎是連續折騰了一個多月,因爲線上已經在運行的要通過cp文件等方法來弄。

HSF的那段看到的很多是在技術深度上的問題,而T4的這段設計,現在回顧最主要的問題是這個技術領域視野的嚴重問題,所以我認爲作爲架構師,在相應的技術領域要有足夠的視野,一定要知道這個領域的工程界、學術界是什麼情況,這樣對自己在結合目的、目標以及一些約束條件下做出更合理的技術選型是非常重要的,之前也寫過一篇關於如何擴充技術視野的文章。

異地多活的設計

到了做異地多活這個階段,也許是因爲有了前面的一些積累,總結反思,我自己覺得異地多活的設計更多的是選擇,至於對錯我總體認爲還好,所以這裏我就講一些異地多活設計上爲了解決核心問題所面臨的一些權衡選擇,而這也是架構師在做設計上非常重要的一個部分,如何去根據各種約束來做一些方案的權衡選擇。

異地多活在覈心問題上要解決的是請求封閉、數據一致性這兩個關鍵問題,在爲了解決這兩個問題的設計上,參考了工程界的一些情況,最後發現我們所面臨的狀況還是很不一樣。

在這裏就拋出一些異地多活設計上所面臨的選擇,我就不去講我的選擇邏輯之類的了,方便大家思考,以及交流探討。

  1. 流量/數據拆分的規則到底按什麼好?買家/賣家/商品?
  2. 分流的規則和數據庫分庫分表的規則的關係:松耦合 Vs 強綁定?
  3. 數據同步策略的選擇:部分 Vs 全量?
  4. 數據一致性的保障,在哪些層面做,CAP?
  5. 部署的選擇:兩地 Vs 三地,地域的分佈選擇?
  6. 落地節奏,一年?兩年?三年?

關於異地多活設計的文章往上也有很多了,感興趣的之後也可以去翻翻。

近幾年或現在在做的諸如統一調度、雲化這些事情暫時還不太適合公開層面來講,以後有機會了再來講講在這些事情上系統設計上的一些狀況,所以就以這三個cases來講講解決核心問題的設計這個環節。

架構師應具備的能力總結

最後根據目的、可衡量的目標、核心問題提煉、解決核心問題的設計這些環節,總結提煉下我覺得架構師需要具備的能力:

  1. 對業務所面臨的挑戰的理解,從業務挑戰到技術挑戰映射的能力,或者說技術抽象的能力;
  2. 知識儲備以及考慮的全面性,從開發、部署、運行、維護態;
  3. 技術選型能力,極厚的技術功底,開闊的技術視野;
  4. 在各種約束條件下權衡選擇的能力,原則。

所以架構師我覺得絕對不是爛大街的頭銜,要做到一個合格的架構師還是相當難的,尤其是工程類型的架構師,需要長期的實戰、經驗積累。

系統設計一直是我認爲最難講的內容,這個系列的文章能寫到現在的第4篇,主要還是因爲我在內部嘗試做的一個系統設計的培訓,非常感謝一幫同學支持了我做這個培訓,要不是他們的參與,我覺得不可能寫這些文章,也不可能較爲體系化的說說系統設計,並且更重要的是讓我覺得系統設計這個東西其實還是可以不講的那麼虛的,以及系統設計的技能一定程度上確實也是可以培養的。

這個系列的文章會按照聊聊系統設計的套路來寫,寫的時候會理論結合實踐,實踐主要是講我自己在相應的點上的一些經歷:

更多系列內容:點擊這裏

原文出處:阿里雲大學開發者社區

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章