朱曄的網際網路架構實踐心得S1E9:架構評審一百問和設計文件五要素
本文我會來說說我認為架構評審中應該看的一些點,以及我寫設計文件的一些心得。助你在架構評審中過五關斬六將,助你寫出能讓人收藏點讚的設計文件。
技術架構評審
架構評審或技術方案評審的價值在於集眾人的力量大家一起來分析看看方案裡是否有坑,方案上線後是否會遇到不可逾越的重大技術問題,提前儘可能把一些事情先考慮到提出質疑其實對專案的健康發展有很大的好處。很多公司都有架構評審委員會都有架構評審的流程,做業務的兄弟要麼看到這個流程往往心驚膽戰害怕自己做的方案被斃了咋整,要麼就是認為這是一種過場,隨便糊弄一點文件發給委員會看一下就算過去了。我做過架構評審委員也做過提交評審方案的業務兄弟,不管哪個角色我都不害怕而是喜歡這一流程,評審這個事情做的好其實可以很享受,大家都是一起學習的過程,不存在誰為難誰。下面說說我覺得架構評審(非程式碼評審)中看重的需要評審的一些點。
元件選型
- 為什麼選A不選B呢?
- A不是開源的,出了問題怎麼辦?
- B雖然是開源的,但是是Erlang寫的,公司沒人能看懂怎麼辦?
- C我看待解決的Issues還有很多,有沒有去了解過?
- 這個元件在效能方面你是否瞭解過?
- 開源的免費版本不支援叢集怎麼辦?
- 如果徹底要自己寫這個元件有沒有可能性?
元件特別是儲存元件選型挺重要的,真心建議事先可以有那麼幾周的時間搭一個高可用的叢集,使用接近於真實的資料對元件進行壓測(你看之前我部落格上的Mongodb的壓測文章停火的,說明很多人沒有這個時間和條件對一些元件進行壓測)。眼見為實耳聽為虛,自己通過壓測對比一下自己得出的資料和公開的資料是否有差異,如果有的話說不定還能發現自己使用上的一些問題。儘量還是選用使用的人多的開源元件吧,出了問題至少Patch不會來的太慢。
效能
- 我們需求的TPS、QPS和RT是多少?
- 整體設計上會做到的TPS、QPS和RT是多少?
- 隨著資料量的增大系統效能會不會出現明顯問題?
- 系統哪個環節會是最大的瓶頸?
- 是否打算做壓力測試,壓力測試方案是怎麼樣的?
- 怎麼提高前端使用者的訪問流暢性?
對於重要的專案,建議做一下整體壓測,沒有經過壓測得出來的估計的結論往往可能是錯的,我們總以為最終會死在最後的儲存上,但是很可能早早就死在了程式的低階錯誤上,比如在一些儲存元件的Client使用上,如果沒把控好最佳實踐(把應該作為單例使用Clinet每次都去建立一次,預設的執行緒數小的可憐應該重新配置但是保留了預設值),死的非常難看。
可伸縮性
- 每一個環節是否都是可以橫向擴充套件的?
- 擴容需要怎麼做手動還是自動?
- 資料庫不能橫向擴充套件怎麼辦?
- 縱向擴充套件有多少效果?
- 橫向擴充套件是否是線性的?
- 擴充套件後是否可以提高響應速度?
靈活性
- 是否有了解過產品層面以後會怎麼發展?
- 模組A是否能拆分出去獨立為其它業務服務?
- 模組B是否可以替換為另一種第三方資料來源?
- 如果流程有變,需要多大的工作量來適應?
- 業務是否可以做到可配?
- 為什麼A和B都有差不多的邏輯?
- 是否考慮到了A業務的實現以後還有B的可能性?
- 如果現在有兩種策略以後擴充套件到了八種策略怎麼做?
- 以後是否可以把這個業務的H5前端適配到PC?
可擴充套件性
- 為什麼A和B都有差不多的邏輯?
- 是否考慮到了A業務的實現以後還有B的可能性?
- 如果現在有兩種策略以後擴充套件到了八種策略怎麼做?
- 以後是否可以把這個業務的H5前端適配到PC?
可靠性
- 是否架構中有單點?
- 故障轉移是怎麼實現的?
- 叢集內部故障轉移需要多久?
- MQ或儲存出現問題的時候系統會怎麼樣?
- MQ或儲存出現問題又恢復了系統是否會自己恢復?
- 是否考慮過異地故障轉移的方案?
- 是否考慮過多活的方案?
- 是否有資料丟失的可能性?
- 資料丟失後是否可以恢復?
- 系統徹底掛了對其它業務的影響是什麼?
- 系統徹底掛了是否可以有線下的方式走業務?
安全性
- 是否徹底避免SQL注入和XSS?
- 是否做了風控策略?
- 是否有防刷保護機制?
- 資料庫拖庫了會怎麼樣?
- 是否有資料洩露的可能性?
- 資料的許可權怎麼控制的?
- 功能的許可權是怎麼控制的?
- 是否做了日誌審計?
- 受到了DDOS攻擊怎麼辦?
- 資料傳輸是否加密驗籤?
相容性
- 老的系統打算怎麼辦?
- 怎麼進行新老系統替換?
- 新老系統能否來回切換?
- 別的系統怎麼連線你這套新服務?
- 上下游依賴是否梳理過,影響範圍多大?
- 上下游改造的難度怎麼樣?
- 上下游改造有排期嗎?
- 上下游改造的計劃和通知時間確定了嗎?
- 使用了新的資料來源資料怎麼遷移?
- 使用了新的技術老專案開發能否適應?
彈性處理
- 這個資料重複消費會怎麼樣?
- 這個介面重複呼叫會怎麼樣?
- 是否考慮了服務降級?哪些業務支援降級?
- 是否考慮了服務熔斷?熔斷後怎麼處理?
- 是否考慮了服務限流?限流後客戶端表現怎麼樣?
- 佇列爆倉會怎麼樣?
- 是否考慮了隔離性?
事務性
- 這段業務由誰保證事務性?
- 資料庫事務回滾後會怎麼樣?
- 服務呼叫了失敗怎麼辦?
- 佇列補償怎麼做的?
- 服務呼叫補償怎麼做的?
- 資料補償實現最終一致需要多久?
- 在資料不完整的時候使用者會感知到嗎?
可測試性
- 測試環境和線上的差異多大?
- 是否支援部署多套隔離的測試環境?
- 是否打算做單元測試,覆蓋率目標是多少?
- 測試黑盒白盒工作量的比例是怎麼樣的?
- 是否支援介面層面的自動化測試?
- 是否有可能做UI自動化測試?
- 壓測怎麼造資料?
- 是否可以在線上做壓測?
- 線上壓測怎麼隔離測試資料?
- 是否有測試白名單功能?
可運維性
- 每一個元件對伺服器哪方面的壓力會最大?
- 重新搭建整套系統最快需要多少時間?
- 系統是否可以完全基於原始碼構建?
- 系統是否有初始化或預熱的環節?
- 系統裡哪些環節需要人工參與?
- 資料是否需要定期歸檔處理?
- 會不會有突發的資料量業務量增大?
- 隨著時間的推移如果壓力保持不變的話系統需要怎麼來巡檢和維護?
- 怎麼在容器裡進行部署?
監控
- 業務層面哪些指標需要監控和報警?
- 應用層面系統內部是否有暴露了一些指標作監控和報警?
- 系統層面使用的中介軟體和儲存是否有監控報警?
- 是否所有環節都接入了全鏈路跟蹤?
- 出現報警的時候應該由誰來處理?
- 每一個模組是否有固定的主要和次要負責人?
- 有沒有可能系統出了問題無法通過監控指標體現?
- 哪些指標需要上大屏由監控進行7*24監控?
看了這麼多問題可能會覺得這架構設計是沒法做了,其實不同階段的專案有不同的目標,我們不會在專案起步的時候做99.99%的可用性支援百萬QPS的架構,高效完成專案的業務目標也是架構考慮的因素之一。而且隨著專案的發展,隨著公司中介軟體和容器的標準化,很多架構的工作被標準化替代,業務程式碼需要考慮架構方面伸縮性運維性等等的需求越來越少,慢慢的這些工作都能由架構和運維團隊來接。一開始的時候我們可以花一點時間來考慮這些問題,但是不是所有的問題都需要有最終的方案。
技術設計文件
如果你在Google搜尋架構設計文件、技術設計文件、概要設計文件可以搜尋到很多模板,很多公司也會以這些模板作為設計文件的模板來讓大家填寫。對於大部分所謂的專案只是一個專案中的一個小環節是一個具體的業務邏輯,因此總是可以看到大家寫的所謂的技術設計文件只能填滿文件的20%,其餘都不知道怎麼寫。當你不知道文件應該寫哪些內容的時候可以這麼來考慮問題,就是你這個專案接下去是要賣給別人來用的,你沒有機會當面和他把這個專案說清楚,你只能通過文件來把事情寫清楚,別人就給你一次機會,如果看不懂你文件表達的意思,不能理解你的專案,你的專案就賣不出去不值錢,這個時候你一定會從各個角度來剖析你的系統想盡一切辦法來把事情說清楚,用這個方法逼一下自己的,你的文件會很優秀。接下去我想說一下如果是我的話我看重技術設計的哪些部分以及這些部分的文件的寫作方式,這些內容構成了一個必要的(概要)設計文件,算是拋磚引玉。
交代背景和需求全貌
在這裡,推薦使用腦圖在技術角度給出一下自己理解的專案需求的分佈。PRD中的產品功能腦圖可以和這裡技術角度的腦圖有差異,在說清楚需求的同時側重技術層面,體現在:
- 可以不按照需求的功能點進行歸類而是按照實際專案歸類,把需求列在實際的專案下面
- 可以區分需求是自己乾的還是呼叫外部的介面,可以在圖上以不同的形態提現
- 可以畫出功能之間的依賴關係,以虛線實線進一步區分依賴的程度
- 可以在圖上體現需求的優先順序以及需求目前的進展和負責人,這樣基本一個圖就可以看清楚這個專案需要消耗多少資源需要多久可以結束
看了這個圖基本產品需求就可以理解個大概,具體的細節規則可以進一步參考PRD。
系統架構圖
在本系列文章的第二到第五篇中,我都配了一個架構圖。架構圖需要傳遞清楚下面的資訊:
- 專案由哪些模組、服務、快取、儲存構成,可以以不同的圖案和顏色代表不同型別
- 模組之間的依賴關係(當然,也可以從資料的流向角度來畫)
- 核心流程的步驟,沿著圖上的1、2、3基本就可以大概瞭解核心流程的實現
- 可以用大的框把元件進行分組來描述元件的部署方式(比如相同機器上承載的元件在一個框內)
- 可以以邊框的虛實來分類專案內的元件或三方元件,可以以箭頭的虛實來標記主要流程次要流程等等
UML裡會有一些具體的分類,什麼類圖、元件圖、部署圖等等,我覺得不必拘泥於這些細節,通過線線框框的架構圖能把模組和模組之間的關係表述請求,然後再配以一定的文字來說明每一個元件即可。我自己常用的是gliffy,只要能說清楚,Word畫也可以。根據專案的大小,圖上的模組不一定是需要獨立部署的程序,模組也可以是專案內部的一個模組或類。對於複雜的專案,要畫一個圖說清楚很難,可以畫一個大的架構圖,然後針對每一個模組或流程再細化畫不同層次的圖。
對外API定義
API的詳細定義可以由Swagger UI、Spring REST Doc、Miredot等等工具生成,這些生成的介面是按照程式碼來組織層次關係的,只能體現介面的引數定義不能體現介面的形態等,是沒有思想的,不適合用來閱讀,只適合用來參考。因此還是建議做一個腦圖來總體闡述一下介面的:
- 分類,按業務功能的分類,按受眾的分類等等
- 形式(圖上不同的顏色),同步還是非同步(結果不在響應中,單獨的回撥返回),單條還是批量,資料介面還是頁面呼叫等等
- 重要性(圖上文字後的星號),比如重點標記主流程的介面
圖上可以不顯示出引數清單,但可以以簡單的文字來描述重要引數,比如下單介面:->@使用者身份,優惠券ID*,[{商品ID,數量}]<-訂單號,下單結果(0-失敗,1-成功)。(->代表輸入,<-代表輸出,[]代表陣列,@代表隱式引數,*代表可空引數等等)。
之前強調過好多次涉及到和外部互動的API是設計中非常重要的一個環節,不僅僅體現了系統對外輸出的能力,也體現了系統設計在安全性、複用性、封裝等方面的平衡。
互動時序
時序圖的表達非常重要,可以表現需求腦圖、架構圖和API腦圖無法表現出來的幾個方面,清晰展現了某個事情:
- 關鍵的利益關係方。這個事情由哪幾個方面構成,可以是使用者、甲方、乙方這麼來分,也可以是使用者、APP客戶端、服務端這麼來分
- 每一方在做什麼,依賴的又是什麼,整個順序是怎麼樣的
- 技術層面這是同步介面、還是回撥、還是非技術的線下流程
- 還可以在圖上表現出可選邏輯,條件判斷邏輯,迴圈邏輯等等
我覺得能在比較高的層面說一下技術(對接)流程即可,不一定要詳細到類和類之間的互動,類和類之間的互動閱讀程式碼或直接看全鏈路呼叫的圖就可以。如果專案有多個合作方多個依賴方,專案流程比較複雜,那麼序列圖是能把這個事情說清楚的最好的方式。
我們輸入類似的文字:
title 合作流程
使用者->XX:投資YY標的
XX->YY:同步投資情況,更新可用額度
使用者->YY:在額度內消費
YY->XX:同步消費情況,更新可用額度,更新回款計劃
YY->XX:還款
XX->使用者:回款(已消費部分作為手續費給XX)
opt 線下流程
XX->YY:對於YY使用者的消費出賬單
YY->XX:對賬確認賬單
XX->YY:打款開具發票
End
網站生成類似的時序圖,還可以自由選擇自己喜歡的樣式:
資料庫ER
ER圖就是實體聯絡圖。形式上我們可以在圖上表現幾個點:
- 實體:哪些表
- 實體上的屬性:體現實體之間關係以及實體業務功能的重要欄位
- 聯絡:實體和實體之間的關係,比如一對多,多對一還是多對多之類
在有的時候我們可以省略屬性的型別定義,甚至可以直接省略具體的屬性(實體名和M對N的關係是必須的),把圖簡化為類似下面的部分:
ER圖的資訊量非常大,絕對不是貼上一下表結構的DDL可以替代的,原因是:
- ER圖可以以極小的空間展現很多資訊,這樣我們可以在圖上對業務進行分組,看到全貌
- ER圖展現的是表和表之間的關係,一眼可以看出最重要核心的表是哪些
比如下圖,是否一眼就可以看明白一套P2P金融業務整個資料結構的架構呢:
(隨便畫的圖,不代表任何意義,請不要以這個圖做P2P的表結構設計)
所有的圖,文字只是一個維度,我們要學會利用邊框型別(矩形、圓角矩形),邊框樣式(虛線,實線),填充色,文字顏色,關聯線條粗細顏色樣式,框內ICON來增加我們要表現資訊的維度,最多可以增加到6維+,這種能力是文字很難實現的。一圖勝過千言,所以我一直認為圖是設計文件中非常重要的部分。
其它
之前我說了我們可以以五圖的形式(需求腦圖、架構圖、API腦圖、序列圖、資料庫ER圖)把系統大概介紹一個底朝天,說清楚了需求、架構、對外介面、互動流程和資料結構設計這幾個事情,業務專案說清楚這些足夠了。
對於偏向於中介軟體(不管是基礎中介軟體還是業務中介軟體,中臺)的專案(而不是業務專案),這裡我再補充幾個重要的方面,需要在設計文件中有體現:
- 可靠性:是否有單點的元件,非單點的元件如何做故障轉移
- 高效能:是否有抗突發性能壓力的能力,大概可以滿足多少的TPS和QPS,怎麼去做來實現高效能
- 可擴充套件:隨著壓力上升哪些環節可以做擴充套件,怎麼做擴充套件
- 安全性:哪些手段防突破,萬一突破了後果怎麼樣
- 相容性:和遺留系統怎麼通訊,怎麼做遷移
- …………等等方面
這些點我就不一一展開說了,在第一節說架構評審的時候都有提到過,針對那些問題寫一下自己的設計是怎麼應對的吧。
這些點我認為可以構成一個合格的設計文件,文件的形式不重要,重要的是可以把業務的技術實現梳理清楚,確保我們在開發之前有一個清晰的思路,在開發上線後,文件也是一個後人熟悉系統的非常重要的手段。你可能會提出疑問說這樣的設計文件是不是太粗略了一點,完全沒有體現到軟體層面設計的細節,沒錯是這樣,但是我一直說的是網際網路架構心得,敢問現在網際網路專案從0開始的大專案1到2個月上線,大的版本迭代2週一次,如果設計的時間是五分之一的話,設計也就是2天到一週這樣子,我們有多少時間和能力來細化文件呢,如果能把我這裡說的五要素都做好,對於網際網路專案已經笑死。
還有一點往往會比較可惜,我們或許可以做到在開發之前有一個概要設計文件的產出,但是我們很難做到在系統上線後隨著迭代還能繼續維護第一版產品上線時那個大而全的文件。隨著產品的迭代,我們的技術文件也像PRD迭代文件一樣只說這次迭代的技術改動的話,這種設計文件因為沒有全域性觀意義不大。對於這個情況,我覺得對於每一條業務線的產品,我都建議我們至少能維護大而全的下面這些文件的全量版本:
- 完整表結構(順帶標一下歸檔方案、重要程度)
- 需求全貌
- 對外產品能力輸出全貌
- 整體架構圖
- 關鍵業務互動流程(特別是那種很難說清楚的多方結算關係)
定期回顧一下這五個文件,根據最近的需求改改,可能也只需要花費幾小時的時間,對於大專案其意義往往是新人的靈魂導師(之前我有畫過一個比較複雜系統的架構圖,這個架構圖我看到有人做了桌面)。