此爲筆記
課程鏈接
週二,我們聊了架構出現的歷史背景和推動因素。以史爲鑑,對我們瞭解架構設計的目的很有幫助。談到架構設計,相信每個技術人員都是耳熟能詳,但如果深入探討一下,“爲何要做架構設計?”或者“架構設計目的是什麼?”類似的問題,大部分人可能從來沒有思考過,或者即使有思考,也沒有太明確可信的答案。
架構設計的誤區
關於架構設計的目的,常見的誤區有:
- 因爲架構很重要,所以要做架構設計
這是一句正確的廢話,架構是很重要,但架構爲何重要呢?
例如:不做架構設計系統就跑不起來麼?
其實不然,很多朋友尤其是經歷了創業公司的朋友可能會發現,公司的初始產品可能沒有架構設計,大夥擼起袖子簡單討論一下就開始編碼了,根本沒有正規的架構設計過程,而且也許產品開發速度還更快,上線後運行也還不錯。
例如:做了架構設計就能提升開發效率麼?
也不盡然,實際上有時候最簡單的設計開發效率反而是最高的,架構設計畢竟需要投入時間和人力,這部分投入如果用來儘早編碼,項目也許會更快。
例如:設計良好的架構能促進業務發展麼?
好像有一定的道理,例如設計高性能的架構能夠讓用戶體驗更好,但反過來想,我們照抄微信的架構,業務就能達到微信的量級麼?肯定不可能,不要說達到微信的量級,達到微信的 1/10 做夢都要笑醒了。
- 不是每個系統都要做架構設計嗎
這其實是知其然不知其所以然,系統確實要做架構設計,但還是不知道爲何要做架構設計,反正大家都要做架構設計,所以做架構設計肯定沒錯。
這樣的架構師或者設計師很容易走入生搬硬套業界其他公司已有架構的歧路,美其名曰“參考”“微改進”。一旦強行引入其他公司架構後,很可能會發現架構水土不服,或者運行起來很彆扭等各種情況,最後往往不得不削足適履,或者不斷重構,甚至無奈推倒重來。
- 公司流程要求系統開發過程中必須有架構設計
與此答案類似還有因爲“架構師總要做點事情”,所以要做架構設計,其實都是捨本逐末。因爲流程有規定,所以要做架構設計;因爲架構師要做事,所以要做架構設計,這都是很表面地看問題,並沒有真正理解爲何要做架構設計,而且很多需求並不一定要進行架構設計。如果認爲架構師一定要找點事做,流程一定要進行架構設計,就會出現事實上不需要架構設計但形式上卻繼續去做架構設計,不但浪費時間和人力,還會拖慢整體的開發進度。
- 爲了高性能、高可用、可擴展,所以要做架構設計
能夠給出這個答案,說明已經有了一定的架構經歷或者基礎,畢竟確實很多架構設計都是衝着高性能、高可用……等“高 XX”的目標去的。
但往往持有這類觀點的架構師和設計師會給項目帶來巨大的災難,這絕不是危言聳聽,而是很多實際發生的事情,爲什麼會這樣呢?因爲這類架構師或者設計師不管三七二十一,不管什麼系統,也不管什麼業務,上來就要求“高性能、高可用、高擴展”,結果就會出現架構設計複雜無比,項目落地遙遙無期,團隊天天吵翻天……等各種讓人抓狂的現象,費盡九牛二虎之力將系統整上線,卻發現運行不夠穩定,經常出問題,出了問題很難解決,加個功能要改 1 個月……等各種繼續讓人抓狂的事件。
架構設計的真正目的
那架構設計的真正目的究竟是什麼?
從週二與你分享的架構設計的歷史背景,可以看到,整個軟件技術發展的歷史,其實就是一部與“複雜度”鬥爭的歷史,架構的出現也不例外。簡而言之,架構也是爲了應對軟件系統複雜度而提出的一個解決方案,通過回顧架構產生的歷史背景和原因,我們可以基本推導出答案:架構設計的主要目的是爲了解決軟件系統複雜度帶來的問題。
這個結論雖然很簡潔,但卻是架構設計過程中需要時刻銘記在心的一條準則,爲什麼這樣說呢?
首先,遵循這條準則能夠讓“新手”架構師心中有數,而不是一頭霧水。
新手架構師開始做架構設計的時候,心情都很激動,希望大顯身手,甚至恨不得一出手就設計出世界上最牛的 XX 架構,從此走上人生巔峯,但真的面對具體的需求時,往往都會陷入一頭霧水的狀態:
“這麼多需求,從哪裏開始下手進行架構設計呢?”。
“架構設計要考慮高性能、高可用、高擴展……這麼多高 XX,全部設計完成估計要 1 個月,但老大隻給了 1 周時間”。
“業界 A 公司的架構是 X,B 公司的方案是 Y,兩個差別比較大,該參考哪一個呢?”。
以上類似問題,如果明確了“架構設計是爲了解決軟件複雜度”原則後,就很好回答。
- “這麼多需求,從哪裏開始下手進行架構設計呢?”
——通過熟悉和理解需求,識別系統複雜性所在的地方,然後針對這些複雜點進行架構設計。
- “架構設計要考慮高性能、高可用、高擴展……這麼多高 XX,全部設計完成估計要 1 個月,但老大隻給了 1 周時間”
——架構設計並不是要面面俱到,不需要每個架構都具備高性能、高可用、高擴展等特點,而是要識別出複雜點然後有針對性地解決問題。
- “業界 A 公司的架構是 X,B 公司的方案是 Y,兩個差別比較大,該參考哪一個呢?”
——理解每個架構方案背後所需要解決的複雜點,然後才能對比自己的業務複雜點,參考複雜點相似的方案。
其次,遵循這條準則能夠讓“老鳥”架構師有的放矢,而不是貪大求全。
技術人員往往都希望自己能夠做出最牛的東西,架構師也不例外,尤其是一些“老鳥”架構師,爲了證明自己的技術牛,可能會陷入貪大求全的焦油坑而無法自拔。例如:
“我們的系統一定要做到每秒 TPS 10 萬”。
“淘寶的架構是這麼做的,我們也要這麼做”。
“Docker 現在很流行,我們的架構應該將 Docker 應用進來”。
以上這些想法,如果拿“架構設計是爲了解決軟件複雜度”這個原則來衡量,就很容易判斷。
- “我們的系統一定要做到每秒 TPS 10 萬”
——如果系統的複雜度不是在性能這部分,TPS 做到 10 萬並沒有什麼用。
- “淘寶的架構是這麼做的,我們也要這麼做”
——淘寶的架構是爲了解決淘寶業務的複雜度而設計的,淘寶的業務複雜度並不就是我們的業務複雜度,絕大多數業務的用戶量都不可能有淘寶那麼大。
- “Docker 現在很流行,我們的架構應該將 Docker 應用進來”
——Docker 不是萬能的,只是爲了解決資源重用和動態分配而設計的,如果我們的系統複雜度根本不是在這方面,引入 Docker 沒有什麼意義。
簡單的複雜度分析案例
我來分析一個簡單的案例,一起來看看如何將“架構設計的真正目的是爲了解決軟件系統複雜度帶來的問題”這個指導思想應用到實踐中。
假設我們需要設計一個大學的學生管理系統,其基本功能包括登錄、註冊、成績管理、課程管理等。當我們對這樣一個系統進行架構設計的時候,首先應識別其複雜度到底體現在哪裏。
性能:一個學校的學生大約 1 ~ 2 萬人,學生管理系統的訪問頻率並不高,平均每天單個學生的訪問次數平均不到 1 次,因此性能這部分並不複雜,存儲用 MySQL 完全能夠勝任,緩存都可以不用,Web 服務器用 Nginx 綽綽有餘。
可擴展性:學生管理系統的功能比較穩定,可擴展的空間並不大,因此可擴展性也不復雜。
高可用:學生管理系統即使宕機 2 小時,對學生管理工作影響並不大,因此可以不做負載均衡,更不用考慮異地多活這類複雜的方案了。但是,如果學生的數據全部丟失,修復是非常麻煩的,只能靠人工逐條修復,這個很難接受,因此需要考慮存儲高可靠,這裏就有點複雜了。我們需要考慮多種異常情況:機器故障、機房故障,針對機器故障,我們需要設計 MySQL 同機房主備方案;針對機房故障,我們需要設計 MySQL 跨機房同步方案。
安全性:學生管理系統存儲的信息有一定的隱私性,例如學生的家庭情況,但並不是和金融相關的,也不包含強隱私(例如玉照、情感)的信息,因此安全性方面只要做 3 個事情就基本滿足要求了:Nginx 提供 ACL 控制、用戶賬號密碼管理、數據庫訪問權限控制。
成本:由於系統很簡單,基本上幾臺服務器就能夠搞定,對於一所大學來說完全不是問題,可以無需太多關注。
還有其他方面,如果有興趣,你可以自行嘗試去分析。通過我上面的分析,可以看到這個方案的主要複雜性體現在存儲可靠性上,需要保證異常的時候,不要丟失所有數據即可(丟失幾個或者幾十個學生的信息問題不大),對應的架構如下:
學生管理系統雖然簡單,但麻雀雖小五臟俱全,基本上能涵蓋軟件系統複雜度分析的各個方面,而且絕大部分技術人員都曾經自己設計或者接觸過類似的系統,如果將這個案例和自己的經驗對比,相信會有更多的收穫。