閱讀502 返回首頁    go 阿裏雲 go 技術社區[雲棲]


提高應用程序可用性的五個要點

可用性問題通常會在你最想不到的地方出現,許多問題都是係統性的問題,而不僅僅是代碼的問題。本文提出了五個要點能夠幫助你的係統在規模增長的同時保證高可用性。
相關圖書推薦,《可伸縮架構:麵向增長應用的高可用》

  構建一個高可用、可伸縮的應用程序不是一件容易的事,也不會是天上掉下來的餡餅。問題總會以你從未預期的方式出現,讓你精心設計的功能對所有用戶都停止工作。

  這些可用性問題通常會在你最想不到的地方出現,甚至一些最嚴重的問題會來自於最不可能出現的地方。

一次簡單的圖標故障
這發生在我親身經曆的一個應用程序中,是一次因為忽視依賴故障的典型案例。該程序向用戶提供了一個服務,為每個頁麵頂部提供一個自定義的圖標,來表示當前登錄的用戶。這個圖標由一個第三方係統負責生成。
有一天,這個生成圖標的第三方係統發生了故障。我們的應用程序卻假設該係統總是會正常運行,因此並不知道如何處理這種情況。結果是,我們的應用程序也跟著發生故障。我們整個係統僅僅是因為圖標生成這樣一個非常小的“功能”,導致無法提供任何服務。
如何才能避免這樣的問題呢?如果我們能夠預料到第三方係統可能發生故障,就可以在設計過程中考慮到這個故障發生的場景,從而發現我們的應用程序也會隨之發生故障。這樣,我們就能添加一些邏輯來檢查第三方服務,在問題發生時刪除圖標,或者在問題發生時捕獲錯誤,避免它傳遞下去並影響頁麵的其他部分。
一次小小的檢查和一些錯誤恢複機製,就可以幫助應用程序保持正常運行。否則,我們的應用程序就會經曆嚴重的服務中斷。
所有這一切都是因為缺少了一個圖標。

  沒人有能夠預料到問題會在何處發生,也不可能依靠測試來發現所有這些問題。許多問題都是係統性的問題,而不僅僅是代碼的問題。

  為了發現這些可用性的問題,我們需要後退一步,係統地去了解應用程序的運行機製。以下是五個你可以關注、並且應當關注的要點,它們能夠幫助你的係統在規模增長的同時保證高可用性:

  • 時刻考慮應對故障
  • 時刻考慮如何伸縮
  • 緩和風險
  • 監控可用性
  • 以可預期及明確的方式來處理可用性問題

讓我們來詳細講解其中的每一個要點。

要點1 :時刻考慮應對故障

  正如Amazon 的CTO Werner Vogels 所說,“所有事情每時每刻都會失敗”。你應當提前為應用程序和服務發生故障而做出計劃。問題遲早會產生。不過現在,我們要講的是如何解決它。

  假設你的應用程序發生了故障,那麼它是如何發生的?當你構建係統的時候,應當在設計和實現的方方麵麵都考慮可用性。例如:

設計

  你有考慮過任何設計模式嗎?你有使用它們來幫助你提升軟件的可用性嗎?

  通過使用一些設計模式,例如捕獲底層異常、重試邏輯和斷路器,可以幫助你捕獲錯誤並盡可能避免影響其他功能。這樣,你就能夠限製問題的影響範圍,即使應用程序的某些部分出現問題,依然能夠提供其他一些有用的功能。

依賴

  如果你依賴的組件出現了故障,你會怎樣做?你如何進行重試?如果問題是一個無法恢複的(硬件)故障,你會怎樣做?如果是一個可恢複的(軟件)故障呢?

  斷路器模式在處理依賴故障時非常有用,因為它們可以降低依賴故障對你的係統的影響。

  如果沒有斷路器,你可能會因為依賴故障而降低係統的性能(例如,需要一個很長的超時機製來檢測故障)。而使用了斷路器,你可以“放棄”並停止使用某個依賴,直到你確認它已經恢複了正常工作。

用戶

  如果出現問題的原因是係統的某個用戶,你會怎樣做?你能夠處理海量的請求嗎?你能夠限製海量的流量嗎?你能夠處理傳入的垃圾數據嗎?如果數據量非常大,你會怎樣做?

  有些時候,拒絕式服務可能來自於“友方”。例如,用戶可能會因為看到一個臨時活動,而導致大量請求增加。或者,用戶程序中的一個bug,可能導致他們向你的應用程序拚命地發送請求。如果這樣的事情發生了,你會怎樣做?流量突增會讓你的應用程序宕機嗎?或者你能否檢測出這種問題,通過限製請求的速度來降低或者消除它們的影響?

要點2 :時刻考慮如何伸縮

  你的係統現在正常運行,並不意味著它明天還能夠繼續正常運行。大多數Web 應用程序的流量都是在不斷增加的。一個今天產生一定流量的網站,明天可能會產生遠比你想象大得多的流量。當你構建係統時,不要隻考慮當前的流量,要考慮未來的流量。

  具體一點,這可能意味著:

  • 設計出能夠增加數據庫數量和容量的架構。
  • 考慮限製你的數據伸縮的原因。當數據庫達到容量極限的時候會發生什麼?你需要確認這些限製因素並在到達極限之前解決它們。
  • 你應當能夠很容易地添加額外的應用程序服務器。這通常需要仔細考慮在何處和如何來維護狀態,以及流量是如何路由的。注1
  • 將靜態流量導向離線提供方。這樣你的係統隻需要處理必要的動態流量。使用外部的內容分發網絡(CDN)不僅可以降低網絡需要處理的流量,也能夠利用CDN 的伸縮效率將靜態內容更快地分發給用戶。
  • 考慮是否可以靜態生成一些動態資源。通常來說,看上去動態顯示的內容實際上大多數是靜態的,並且生成靜態內容可以讓你的應用程序提高可伸縮性。這種“應該靜態的動態資源”有些時候隱藏在你想象不到的地方,如下文中所述。

究竟內容應該是靜態的還是動態的?

  通常,看上去是動態的內容實際上大多數是靜態的。設想一個網站上常見的頂部導航欄,絕大多數時候,其中的內容都是靜態的,但是偶爾也會出現一些動態的內容。

  例如,如果你沒有登錄,頁麵的頂部可能會顯示“請登錄”,如果你已經登錄了則顯示“你好,Lee”(當然前提是你的名稱是Lee)。

  這是否意味著整個頁麵都必須動態生成呢?顯然不是。除了頁麵的登錄/ 問候部分,其他部分都是靜態的,通過CDN 可以輕鬆地進行分發並節省你的計算資源。

  當導航欄中大多數內容都是靜態內容時,你可以在用戶的瀏覽器中動態地將變更內容添加到頁麵上(例如根據具體情況添加“請登錄”或者“你好,Lee”的內容)。通過將這些動態數據進行分組,並與靜態內容加以區分,可以提高Web 頁麵的性能,降低應用程序需要處理的動態數據量。這樣可以提高可伸縮性,並最終提高可用性。

要點3 :緩和風險

  保持係統高可用需要消除係統中的風險。當係統發生故障時,通常我們已經在這之前將故障原因確定為了風險。因此,確定風險是提高可用性的一個重要方法。所有的係統中都存在以下這些風險:

  • 存在係統崩潰的風險
  • 存在數據庫崩潰的風險
  • 存在返回結果不正確的風險
  • 存在網絡連接失敗的風險
  • 存在新部署的軟件功能出現故障的風險

保持係統高可用需要消除風險。但是當係統變得越來越複雜時,消除所有風險也變得越來越不可能實現。保持一個大型係統高可用,更多的是來管理係統的風險,知道這些風險是什麼,哪些風險是可接受的,以及你能夠做什麼來緩和風險。

  我們稱之為風險管理,它是構建高可用係統的核心內容。

  風險管理中的一個部分是風險緩和。風險緩和指的是當問題發生時,我們知道如何去盡可能降低問題所帶來的影響。緩和意味著即使當服務和資源不可用時,依然盡可能確保你的係統以最好的、最完整的狀態工作。風險緩和需要考慮哪些事情可能會出錯,並且立即製訂相應的計劃,以便當問題發生時能夠提供相應的解決方案。

  示例:風險緩和——一個沒有搜索功能的網上商店

  假設有一個售賣T 恤的網上商店。它是一個很常見的在線商店,你可以在它的首頁上瀏覽T 恤,跳轉到其他頁麵查看不同的T 恤分類,並且可以搜索指定風格和類型的T 恤。

  為了實現搜索的功能,通常這類網上商店需要調用一個獨立的搜索引擎,這可能是一個單獨的服務,或者甚至由第三方的搜索服務提供。

  但是,因為搜索功能是一個獨立的功能,你的係統就存在搜索服務不可用的風險。你的風險管理計劃需要確定出該問題,並且將“搜索引擎失敗”列為風險之一。

  如果沒有風險緩和計劃,當搜索服務失敗時,可能會產生一個錯誤頁麵,或者返回不正確或無效的結果——不管怎樣,它都會帶來很差的用戶體驗。

  這個示例中的風險緩和計劃可能是這樣的:

  我們知道最受歡迎的T 恤是紅色條紋T 恤,60% 訪問網站的用戶最終都停留在(並很可能最後會購買)這個產品上。因此,如果搜索服務停止了,我們可以顯示一個“很抱歉”的頁麵,下方是我們最受歡迎的T 恤列表,其中就包括紅色條紋T 恤。

  這會鼓勵遇到這個錯誤頁麵的用戶,繼續瀏覽別人曾經感興趣的T 恤。

  此外,我們還可以顯示一個“下一次購買享受10% 折扣”的優惠券,這樣就可以鼓勵之前沒有進行購買的用戶,在搜索服務恢複正常後,繼續回到我們的網站上進行購買。

  示例演示了什麼是風險緩和,而確認風險、確定該如何處理風險,以及如何實現這些緩和措施的過程則被稱為風險管理。

  風險管理經常會暴露應用程序中未知的、需要立即修複的問題。它還可以用來處理已知的故障問題,減少故障恢複時間或者降低嚴重性。

  可用性和風險管理息息相關。構建一個高可用的係統,主要就是要考慮如何管理風險。

要點4 :監控可用性

  除非你看到問題發生,否則你不會知道應用程序中存在著問題。你應當確保對應用程序進行了適當的監控,以便可以從外部和內部兩個視角來觀察應用程序的運行狀況。

  監控的程度取決於應用程序的特點和要求,但是通常必須具備以下這些監控。

服務器監控

  監控服務器的健康狀況,並且確保它們始終在有效運行。

配置變化監控

  監控係統配置的變化,以便確定它們對應用程序的影響。

應用程序性能監控

  深入了解你的應用程序和服務,確保它們按照預期運行。

人為測試

  從用戶的角度來實時檢測應用程序的運行情況,以便在用戶真正發現問題之前發現它們。

報警

  當問題發生時通知相關人員,以便使問題可以得到快速有效的解決,將對用戶的影響降低到最小。

  如今市麵上有許多非常優秀的監控係統,包括免費和付費的服務。我個人推薦NewRelic,它提供了之前提到的所有監控和報警能力。作為一款軟件即服務(SaaS)的軟件,它能夠支持任何規模的應用係統的監控需求。當你對應用程序和服務進行監控之後,請開始尋找它們的運行趨勢。當你明確了一定的趨勢之後,可以開始尋找一些異常值,將它們作為可能存在的可用性問題。你可以利用這些異常值,在係統發生故障之前通過監控工具來發送警報。除此之外,你還可以在係統增長過程中時刻進行跟蹤,確保可伸縮性計劃的實施。

  你應當為服務間通信建立內部的、私有的運行目標,並持續對它們進行監控。通過這種方式,當出現任何與性能或者可用性相關的問題時,你都可以快速診斷出哪個服務或者係統出現了問題,並定位問題的原因。此外,你可以發現一些“熱點”——即性能超出預期的地方,以及針對這些問題製訂相應的開發計劃。

要點5 :以預測和確定的方式來應對可用性問題

  如果你對監控中所發生的問題置之不理,那麼監控係統就毫無用處。這意味著當問題發生時必須要發出報警,這樣你才能有所行動。除此之外,你應當建立整個團隊都遵循的流程,幫助診斷問題,並輕鬆修複常見的故障問題。

  例如,如果某個係統無法響應,你可能會有一係列措施來解決。這其中可能包括運行一個測試來診斷問題原因,重啟一個已知會導致係統無法響應的守護進程,或者當其他手段都失敗時重啟整個服務器。為常見的故障問題提供標準化流程可以降低係統不可用的時間。此外,它們還可以提供更多有用的診斷信息,幫助工程師團隊找到常見問題的根本原因。

  當觸發某個服務的報警時,該服務的負責人必須是第一個被通知到的。畢竟,他們負責修複自己服務中的所有問題。但是,其他與之緊密相關或依賴的團隊也應當收到報警信息。例如,如果某個團隊使用了一個特殊服務,他們希望知道該服務什麼時候出現故障,從而在問題發生時能夠更加主動地保證自己的係統不受影響。

  這些標準的流程和辦法應當被寫進支持手冊中,團隊中每個負責人人手一份。這本支持手冊還應該包含相關係統和服務的聯係人列表,以及當無法用簡單手段解決問題時,需要上報問題的聯係人列表。

  所有這些流程、辦法以及支持手冊都應該提前準備好,以便當服務出現問題時,值班人員能準確知道如何在不同的情況下進行操作,快速恢複服務。這些流程和辦法之所以非常有效,是因為故障通常都發生在一些不太方便的時間點,例如午夜或者周末這些效率比較低下的時間。這些建議可以幫助你的團隊更聰明、更安全地將係統恢複到可運行狀態。

做好準備

  沒人能夠預測到可用性問題在什麼地方、什麼時間發生。但是你可以假設它們會發生,尤其是當你的係統麵臨越來越多的用戶需求,變得越來越複雜的時候。提前做好處理可用性問題的準備,是降低問題出現概率和嚴重性的最佳方法。
  本文選自《可伸縮架構:麵向增長應用的高可用》,點此鏈接可在博文視點官網查看此書。
                    圖片描述

  想及時獲得更多精彩文章,可在微信中搜索“博文視點”或者掃描下方二維碼並關注。
                         圖片描述

最後更新:2017-06-29 13:31:52

  上一篇:go  Petya勒索病毒疫苗出現,分分鍾讓電腦對病毒免疫
  下一篇:go  MySQL函數