🎯 什麼情境該想到我

當你「面對高並發存取、海量資料處理、高可靠運行的挑戰,需要一份被許多大型網站反覆驗證過的通用招式清單」的時候。

⚙️ 怎麼用(九式 × 五要素的檢查清單)

第一部分:九種架構模式(2.1)

1. 分層(2.1.1) —— 把系統在橫向維度上切成幾個部分,每部分負責相對單一的職責,再透過上層對下層的依賴和呼叫組成完整系統。書中把網站軟體系統分為三層(表 2.1):

職責
應用層負責具體業務和視圖展示,如網站首頁及搜尋輸入和結果展示
服務層為應用層提供服務支援,如使用者管理服務、購物車服務等
資料層提供資料儲存存取服務,如資料庫、快取、檔案、搜尋引擎等

好處是便於分工合作開發和維護;各層之間具有一定獨立性,只要維持呼叫介面不變,各層可獨立演化。挑戰是必須合理規劃層次邊界和介面,開發過程中嚴格遵循約束,禁止跨層次呼叫(應用層直接呼叫資料層)及逆向呼叫(資料層呼叫服務層,或服務層呼叫應用層)。大的分層內部還可以繼續分層:應用層可再細分視圖層(美工負責)和業務邏輯層(工程師負責),服務層可細分資料介面層和邏輯處理層。分層架構是邏輯上的,三層可以部署在同一台機器,隨業務發展再分離部署到不同伺服器。因此在網站規模還很小的時候就應該採用分層架構,將來做大才好應對。

2. 分割(2.1.2) —— 如果分層是橫向切分,分割就是在縱向方面切分:把不同的功能和服務分割開來,包裝成高內聚低耦合的模組單元。書中的例子:在應用層把購物、論壇、搜尋、廣告分割成不同的應用,由獨立團隊負責、部署在不同伺服器上;同一個應用內部若規模龐大,購物業務可再分割成機票酒店業務、3C 業務、小商品業務;即使在這個粒度上,還可以繼續分割成首頁、搜尋列表、商品詳情等模組,這些模組不管邏輯上還是實體部署上都可以是獨立的。服務層同樣可依需要分割成合適的模組。

3. 分散式(2.1.3) —— 分層和分割的一個主要目的,就是讓切分後的模組便於分散式部署,把不同模組部署在不同伺服器上,透過遠端呼叫協同工作。書中列出的常用方案:

  • 分散式應用和服務:改善效能和並發性、加快開發和發布速度、減少資料庫連線資源消耗,還可以讓不同應用複用共同的服務,便於業務功能擴展。
  • 分散式靜態資源:JS、CSS、Logo 圖片等靜態資源獨立分散式部署,並採用獨立的域名,即所謂動靜分離。可減輕應用伺服器負載壓力,用獨立域名加快瀏覽器並發載入速度,並由負責使用者體驗的團隊開發維護。
  • 分散式資料和儲存:大型網站要處理以 P 為單位的海量資料,單台電腦無法提供如此大的儲存空間。除了對傳統關聯式資料庫做分散式部署外,為網站應用而生的各種 NoSQL 產品幾乎都是分散式的。
  • 分散式計算:搜尋引擎的索引建構、資料倉儲的資料分析統計等後台批次處理,目前普遍使用 Hadoop 及其 MapReduce 分散式計算框架,其特點是移動計算而不是移動資料——把計算程式分發到資料所在的位置以加速計算。
  • 此外還有支援線上伺服器設定即時更新的分散式設定、分散式環境下實現並發與協同的分散式鎖、支援雲端儲存的分散式檔案系統

書中警告分散式帶來的四個問題:①服務呼叫必須經過網路,可能嚴重影響效能;②伺服器越多,宕機機率越大,一台宕機可能導致很多應用無法存取,降低可用性;③分散式環境中保持資料一致性非常困難,分散式交易也難以保證;④導致網站依賴錯綜複雜,開發管理維護困難。所以「分散式設計要根據具體情況量力而行,切莫為了分散式而分散式」。

4. 叢集(2.1.4) —— 對於使用者存取集中的模組(比如網站首頁),還需要把獨立部署的伺服器叢集化:多台伺服器部署相同應用構成一個叢集,透過負載平衡設備共同對外提供服務。好處是並發特性更好(要更多容量只需向叢集中加入新機器),而且某台伺服器故障時,負載平衡設備或系統的失效轉移機制會把請求轉發到叢集中其他伺服器,故障不影響使用者使用。書中明講:即使是存取量很小的分散式應用和服務,也至少要部署兩台伺服器構成一個小的叢集,目的就是提高系統的可用性。

5. 快取(2.1.5) —— 把資料存放在距離計算最近的位置以加快處理速度;快取是改善軟體效能的第一手段。四個位置:

  • CDN(內容分發網路):部署在距離終端使用者最近的網路服務商,快取網站的一些靜態資源(較少變化的資料),就近以最快速度回傳;影音網站和入口網站會把使用者存取量大的熱點內容快取在 CDN。
  • 反向代理:屬於網站前端架構的一部分,部署在網站前端,使用者請求到達資料中心時最先存取到它,這裡快取靜態資源,無需轉發給應用伺服器就能回傳。
  • 本地快取:在應用伺服器本地快取熱點資料,應用程式直接存取本機記憶體,無需存取資料庫。
  • 分散式快取:資料量龐大到單機記憶體承受不住,把資料快取在專門的分散式快取叢集中,應用程式透過網路通訊存取。

使用快取的兩個前提條件:①資料存取熱點不均衡,某些資料會被更頻繁地存取,這些資料應該放在快取中;②資料在某個時間段內有效、不會很快過期,否則快取的資料會因失效而產生髒讀,影響結果正確性。快取除了加快存取速度,還能減輕後端應用和資料儲存的負載壓力——這點對網站資料庫架構至關重要,網站資料庫幾乎都是按照有快取的前提來設計負載能力的

6. 非同步(2.1.6) —— 降低耦合的重要手段:業務之間的訊息傳遞不是同步呼叫,而是把一個業務操作分成多個階段,各階段之間透過共享資料的方式非同步執行協作。單機內部可透過多執行緒共享記憶體佇列實現;分散式系統中,多個伺服器叢集透過分散式訊息佇列實現非同步,分散式訊息佇列可看作記憶體佇列的分散式部署。非同步架構是典型的生產者消費者模式,兩者不存在直接呼叫,只要保持資料結構不變,彼此實現可隨意變化。除此之外還有三個特性:

  • 提高系統可用性:消費者伺服器故障時,資料會在訊息佇列伺服器中堆積,生產者可以繼續處理業務請求,系統整體表現無故障;消費者恢復後繼續處理。
  • 加快網站回應速度:生產者處理完業務請求後把資料寫入訊息佇列即可回傳,不需等待消費者處理,回應延遲減少。
  • 消除並發存取高峰:促銷活動、熱點事件會造成並發存取突然增大,用訊息佇列把突增的請求放進去等消費者依次處理,就不會對整體負載造成太大壓力。

提醒:使用非同步方式處理業務可能會對使用者體驗、業務流程造成影響,需要網站產品設計方面的支援

7. 冗餘(2.1.7) —— 網站需要 7×24 小時連續運行,但伺服器隨時可能故障,規模大時宕機是必然事件。要在宕機時仍能繼續服務、不丟資料,就需要一定程度的伺服器冗餘運行與資料冗餘備份,宕機時把其上的服務和資料存取轉移到其他機器。存取和負載很小的服務也必須部署至少兩台伺服器構成叢集。資料庫除了定期備份、存檔保存實現冷備份外,為保證線上業務高可用,還需要主從分離、即時同步實現熱備份。為了抵禦地震、海嘯等不可抗力導致的完全癱瘓,某些大型網站會對整個資料中心進行備份,在全球範圍內部署災備資料中心,程式和資料即時同步到多個災備資料中心。

8. 自動化(2.1.8) —— 目前大型網站的自動化架構設計主要集中在發布運維方面。發布環節出的故障最多,減少人為干預可有效減少故障:

  • 自動化程式碼管理:版本控制、分支建立合併等自動化,工程師只要提交參與開發的產品代號,系統就自動建立開發分支,後期自動合併。
  • 自動化測試:提交測試後系統自動部署到測試環境,啟動自動化測試案例,發送測試報告並向系統回饋結果。
  • 自動化安全檢測:透過靜態安全掃描及部署到安全測試環境進行攻擊測試,評估安全性。
  • 自動化部署:把工程程式碼自動部署到線上生產環境。

運行期則有:自動化監控(心跳檢測、監控效能指標與應用關鍵資料指標)、自動化報警(超出預設閾值就向相關人員發送警訊)、自動化失效轉移(把失效伺服器從叢集隔離出去)、自動化失效恢復(故障消除後重啟服務、同步資料保證一致性)、自動化降級(存取高峰超出最大處理能力時,拒絕部分請求及關閉部分不重要的服務,把負載降到安全水平)、自動化分配資源(把閒置資源分配給重要的服務,擴大其部署規模)。

9. 安全(2.1.9) —— 書中列出的手法:透過密碼和手機校驗碼進行身分認證;登入、交易等操作需要對網路通訊加密,伺服器上儲存的敏感資料(如使用者資訊)也做加密處理;為防止機器人程式濫用網路資源攻擊網站,使用驗證碼識別;對於常見的 XSS 攻擊、SQL 注入,進行編碼轉換等相應處理;對垃圾資訊、敏感資訊進行過濾;對交易轉帳等重要操作根據交易模式和交易資訊進行風險控制

第二部分:五大核心架構要素(第 3 章)

除了當前的系統功能需求外,軟體架構還需要關注性能、可用性、伸縮性、擴展性、安全性這 5 個架構要素;架構設計過程中需要平衡這 5 個要素之間的關係,也可以透過考察這些要素來衡量一個軟體架構設計的優劣。

性能(3.1) —— 使用者無法忍受回應緩慢的網站,打開緩慢會導致嚴重的使用者流失;很多時候性能問題是網站架構升級最佳化的觸發器。從瀏覽器到資料庫,影響使用者請求的所有環節都可以最佳化:

  • 瀏覽器端:瀏覽器快取、頁面壓縮、合理布局頁面、減少 Cookie 傳輸。
  • CDN:把靜態內容分發至離使用者最近的網路服務商機房,用最短存取路徑取得資料。
  • 反向代理:在網站機房部署,快取熱點檔案,加快回應、減輕應用伺服器負載。
  • 應用伺服器端:本地快取與分散式快取,用記憶體中的熱點資料處理請求。
  • 非同步操作:把請求送到訊息佇列等待後續處理,當前請求直接回傳回應。
  • 叢集:多台應用伺服器組成叢集共同對外服務,提高整體處理能力。
  • 程式碼層面:多執行緒、改善記憶體管理。
  • 資料庫端:索引、快取、SQL 最佳化等手段都已比較成熟;NoSQL 則透過最佳化資料模型、儲存結構、伸縮特性等在效能上的優勢日趨明顯。

衡量指標:回應時間、TPS、系統性能計數器。這些指標也是網站監控的重要參數,可用來分析系統瓶頸、預測網站容量、對異常指標報警。性能符合預期只是必要條件——還必須考察超出負載設計能力的高並發情況下可能出現的性能問題,並保證長時間持續運行且存取壓力不均勻時仍保持穩定的性能特性

可用性(3.2) —— 網站宕掉輕則影響聲譽,重則損失金錢與使用者。幾乎所有網站都承諾 7×24 可用,但沒有網站能做到完全的 7×24;扣除故障時間換算成可用性指標,一些知名大型網站可以做到4 個 9 以上,也就是可用性超過 99.99%。因為網站用的是普通商用伺服器,設計目標本身不保證高可用,大型網站通常有上萬台伺服器、每天必定有一些宕機,所以高可用架構設計的前提是「必然會出現伺服器宕機」,目標是宕機時服務或應用依然可用

  • 主要手段是冗餘:應用部署在多台伺服器上同時提供存取,資料儲存在多台伺服器上互相備份。
  • 應用伺服器:多台透過負載平衡設備組成叢集,任一台宕機只需把請求切換到其他伺服器;前提是應用伺服器上不能保存請求的工作階段(session)資訊,否則宕機會話丟失,轉發也無法完成業務處理。
  • 儲存伺服器:需要對資料即時備份,宕機時把資料存取轉移到可用伺服器,並進行資料恢復,以保證繼續有伺服器宕機時資料依然可用。
  • 除了運行環境,高可用還需要軟體開發過程的品質保證:預發布驗證、自動化測試、自動化發布、灰度發布,減少把故障引入線上環境的可能。

衡量標準:假設系統中任何一台或多台伺服器宕機、以及出現各種不可預期的問題時,系統整體是否依然可用。

伸縮性(3.3) —— 定義:透過不斷向叢集中加入伺服器的手段,來緩解不斷上升的使用者並發存取壓力和不斷增長的資料儲存需求。衡量標準:是否可以用多台伺服器建構叢集、是否容易向叢集中添加新伺服器、加入後是否能提供和原伺服器無差別的服務、叢集中可容納的伺服器總數是否有限制。

  • 應用伺服器叢集:只要伺服器上不保存資料,所有伺服器都是對等的,用合適的負載平衡設備就可以不斷加入伺服器。
  • 快取伺服器叢集:加入新伺服器可能導致快取路由失效,進而使叢集中大部分快取資料無法存取;雖然可從資料庫重新載入,但若應用已嚴重依賴快取,可能導致整個網站崩潰,需要改進快取路由演算法保證快取資料的可存取性。
  • 關聯式資料庫:雖支援資料複製、主從熱備等機制,但很難做到大規模叢集的可伸縮性,伸縮性方案必須在資料庫之外實現,透過路由分區等手段把部署有多個資料庫的伺服器組成叢集。
  • NoSQL:先天為海量資料而生,對伸縮性的支援通常非常好,可在較少運維參與下實現叢集規模的線性伸縮。

擴展性(3.4) —— 不同於其他架構要素主要關注非功能性需求,擴展性直接關注網站的功能需求:如何設計架構使其能快速回應需求變化。衡量標準:增加新的業務產品時,是否可以對現有產品透明無影響,不需要任何改動或很少改動既有業務功能就能上線新產品;不同產品之間是否很少耦合,一個產品改動對其他產品無影響。主要手段是事件驅動架構分散式服務(書中此處原文寫作「網站可伸縮架構的主要手段」,依上下文屬 3.4 擴展性一節):

  • 事件驅動架構:通常利用訊息佇列實現,把使用者請求和其他業務事件構造成訊息發布到訊息佇列,處理者作為消費者取得訊息處理。訊息產生與訊息處理分離,可以透明地增加新的訊息生產者任務或新的訊息消費者任務
  • 分散式服務:把業務和可複用服務分離開來,透過分散式服務框架呼叫。新增產品可透過呼叫可複用服務實現自身業務邏輯,對現有產品沒有任何影響;可複用服務升級變更時,也可以提供多版本服務對應用實現透明升級,不需要強制應用同步變更。
  • 大型網站為保持市場地位還會吸引第三方開發者呼叫網站服務、使用網站資料開發周邊產品,主要途徑是開放平台介面

安全性(3.5) —— 網站的安全架構就是保護網站不受惡意存取和攻擊,保護網站的重要資料不被竊取。衡量標準:針對現存和潛在的各種攻擊與竊密手段,是否有可靠的應對策略。(書中本節僅此兩句層級的內容,具體手法見 2.1.9 安全模式。)

🧪 我實際套用的紀錄

  • (待填)

⚠️ 注意 / 什麼時候不適用

  • 書中 2.1.3 明講:「分散式設計要根據具體情況量力而行,切莫為了分散式而分散式。」分散式會帶來網路效能損耗、宕機機率上升、資料一致性困難、依賴錯綜複雜四個代價,不要把它當成預設答案。
  • 2.1.6:非同步可能影響使用者體驗與業務流程,需要產品設計方面的支援,不是純技術決定。
  • 2.1.5:快取有兩個前提(熱點不均衡、時間段內有效),不成立時快取只會帶來髒讀。
  • 2.3 小結:「模式受其適用場景限制,對系統的要求和約束也很多,不恰當地使用模式只會畫虎不成反類犬」;好的設計不是生搬硬套某個模式,而是對問題深刻理解之上的創造與創新

🔗 相關工具