原文鏈接
可用性問題通常會在你最想不到的地方出現(xiàn),許多問題都是系統(tǒng)性的問題趾断,而不僅僅是代碼的問題。本文提出了五個要點能夠幫助你的系統(tǒng)在規(guī)模增長的同時保證高可用性。
如您對可用性不是很了解凡壤,試試在微信后臺回復(fù)“可用性”來了解更多。
相關(guān)圖書推薦耙替,《可伸縮架構(gòu):面向增長應(yīng)用的高可用》
構(gòu)建一個高可用亚侠、可伸縮的應(yīng)用程序不是一件容易的事,也不會是天上掉下來的餡餅俗扇。問題總會以你從未預(yù)期的方式出現(xiàn)硝烂,讓你精心設(shè)計的功能對所有用戶都停止工作。
這些可用性問題通常會在你最想不到的地方出現(xiàn)铜幽,甚至一些最嚴重的問題會來自于最不可能出現(xiàn)的地方滞谢。
一次簡單的圖標故障
這發(fā)生在我親身經(jīng)歷的一個應(yīng)用程序中,是一次因為忽視依賴故障的典型案例啥酱。該程序向用戶提供了一個服務(wù)爹凹,為每個頁面頂部提供一個自定義的圖標厨诸,來表示當前登錄的用戶镶殷。這個圖標由一個第三方系統(tǒng)負責(zé)生成。
有一天微酬,這個生成圖標的第三方系統(tǒng)發(fā)生了故障绘趋。我們的應(yīng)用程序卻假設(shè)該系統(tǒng)總是會正常運行,因此并不知道如何處理這種情況颗管。結(jié)果是陷遮,我們的應(yīng)用程序也跟著發(fā)生故障。我們整個系統(tǒng)僅僅是因為圖標生成這樣一個非常小的“功能”垦江,導(dǎo)致無法提供任何服務(wù)帽馋。
如何才能避免這樣的問題呢?如果我們能夠預(yù)料到第三方系統(tǒng)可能發(fā)生故障,就可以在設(shè)計過程中考慮到這個故障發(fā)生的場景绽族,從而發(fā)現(xiàn)我們的應(yīng)用程序也會隨之發(fā)生故障姨涡。這樣,我們就能添加一些邏輯來檢查第三方服務(wù)吧慢,在問題發(fā)生時刪除圖標涛漂,或者在問題發(fā)生時捕獲錯誤,避免它傳遞下去并影響頁面的其他部分检诗。
一次小小的檢查和一些錯誤恢復(fù)機制匈仗,就可以幫助應(yīng)用程序保持正常運行。否則逢慌,我們的應(yīng)用程序就會經(jīng)歷嚴重的服務(wù)中斷悠轩。
所有這一切都是因為缺少了一個圖標。
沒人有能夠預(yù)料到問題會在何處發(fā)生攻泼,也不可能依靠測試來發(fā)現(xiàn)所有這些問題哗蜈。許多問題都是系統(tǒng)性的問題,而不僅僅是代碼的問題坠韩。
為了發(fā)現(xiàn)這些可用性的問題距潘,我們需要后退一步,系統(tǒng)地去了解應(yīng)用程序的運行機制只搁。以下是五個你可以關(guān)注音比、并且應(yīng)當關(guān)注的要點,它們能夠幫助你的系統(tǒng)在規(guī)模增長的同時保證高可用性:
時刻考慮應(yīng)對故障
時刻考慮如何伸縮
緩和風(fēng)險
監(jiān)控可用性
以可預(yù)期及明確的方式來處理可用性問題
讓我們來詳細講解其中的每一個要點氢惋。
正如Amazon 的CTO Werner Vogels 所說洞翩,“所有事情每時每刻都會失敗”。你應(yīng)當提前為應(yīng)用程序和服務(wù)發(fā)生故障而做出計劃焰望。問題遲早會產(chǎn)生骚亿。不過現(xiàn)在,我們要講的是如何解決它熊赖。
假設(shè)你的應(yīng)用程序發(fā)生了故障来屠,那么它是如何發(fā)生的?當你構(gòu)建系統(tǒng)的時候震鹉,應(yīng)當在設(shè)計和實現(xiàn)的方方面面都考慮可用性俱笛。例如:
你有考慮過任何設(shè)計模式嗎?你有使用它們來幫助你提升軟件的可用性嗎传趾?
通過使用一些設(shè)計模式迎膜,例如捕獲底層異常、重試邏輯和斷路器浆兰,可以幫助你捕獲錯誤并盡可能避免影響其他功能磕仅。這樣珊豹,你就能夠限制問題的影響范圍,即使應(yīng)用程序的某些部分出現(xiàn)問題榕订,依然能夠提供其他一些有用的功能平夜。
如果你依賴的組件出現(xiàn)了故障,你會怎樣做卸亮?你如何進行重試忽妒?如果問題是一個無法恢復(fù)的(硬件)故障,你會怎樣做兼贸?如果是一個可恢復(fù)的(軟件)故障呢段直?
斷路器模式在處理依賴故障時非常有用,因為它們可以降低依賴故障對你的系統(tǒng)的影響溶诞。
如果沒有斷路器鸯檬,你可能會因為依賴故障而降低系統(tǒng)的性能(例如,需要一個很長的超時機制來檢測故障)螺垢。而使用了斷路器喧务,你可以“放棄”并停止使用某個依賴,直到你確認它已經(jīng)恢復(fù)了正常工作枉圃。
如果出現(xiàn)問題的原因是系統(tǒng)的某個用戶功茴,你會怎樣做?你能夠處理海量的請求嗎孽亲?你能夠限制海量的流量嗎坎穿?你能夠處理傳入的垃圾數(shù)據(jù)嗎?如果數(shù)據(jù)量非常大返劲,你會怎樣做玲昧?
有些時候,拒絕式服務(wù)可能來自于“友方”篮绿。例如孵延,用戶可能會因為看到一個臨時活動,而導(dǎo)致大量請求增加亲配〕居Γ或者,用戶程序中的一個bug弃榨,可能導(dǎo)致他們向你的應(yīng)用程序拼命地發(fā)送請求菩收。如果這樣的事情發(fā)生了,你會怎樣做鲸睛?流量突增會讓你的應(yīng)用程序宕機嗎?或者你能否檢測出這種問題坡贺,通過限制請求的速度來降低或者消除它們的影響官辈?
你的系統(tǒng)現(xiàn)在正常運行箱舞,并不意味著它明天還能夠繼續(xù)正常運行。大多數(shù)Web 應(yīng)用程序的流量都是在不斷增加的拳亿。一個今天產(chǎn)生一定流量的網(wǎng)站晴股,明天可能會產(chǎn)生遠比你想象大得多的流量。當你構(gòu)建系統(tǒng)時肺魁,不要只考慮當前的流量电湘,要考慮未來的流量。
具體一點鹅经,這可能意味著:
設(shè)計出能夠增加數(shù)據(jù)庫數(shù)量和容量的架構(gòu)寂呛。
考慮限制你的數(shù)據(jù)伸縮的原因。當數(shù)據(jù)庫達到容量極限的時候會發(fā)生什么瘾晃?你需要確認這些限制因素并在到達極限之前解決它們贷痪。
你應(yīng)當能夠很容易地添加額外的應(yīng)用程序服務(wù)器。這通常需要仔細考慮在何處和如何來維護狀態(tài)蹦误,以及流量是如何路由的劫拢。注1
將靜態(tài)流量導(dǎo)向離線提供方。這樣你的系統(tǒng)只需要處理必要的動態(tài)流量强胰。使用外部的內(nèi)容分發(fā)網(wǎng)絡(luò)(CDN)不僅可以降低網(wǎng)絡(luò)需要處理的流量舱沧,也能夠利用CDN 的伸縮效率將靜態(tài)內(nèi)容更快地分發(fā)給用戶。
考慮是否可以靜態(tài)生成一些動態(tài)資源偶洋。通常來說狗唉,看上去動態(tài)顯示的內(nèi)容實際上大多數(shù)是靜態(tài)的,并且生成靜態(tài)內(nèi)容可以讓你的應(yīng)用程序提高可伸縮性涡真。這種“應(yīng)該靜態(tài)的動態(tài)資源”有些時候隱藏在你想象不到的地方分俯,如下文中所述。
究竟內(nèi)容應(yīng)該是靜態(tài)的還是動態(tài)的哆料?
通常缸剪,看上去是動態(tài)的內(nèi)容實際上大多數(shù)是靜態(tài)的。設(shè)想一個網(wǎng)站上常見的頂部導(dǎo)航欄东亦,絕大多數(shù)時候杏节,其中的內(nèi)容都是靜態(tài)的,但是偶爾也會出現(xiàn)一些動態(tài)的內(nèi)容典阵。
例如奋渔,如果你沒有登錄,頁面的頂部可能會顯示“請登錄”壮啊,如果你已經(jīng)登錄了則顯示“你好嫉鲸,Lee”(當然前提是你的名稱是Lee)。
這是否意味著整個頁面都必須動態(tài)生成呢歹啼?顯然不是玄渗。除了頁面的登錄/ 問候部分座菠,其他部分都是靜態(tài)的,通過CDN 可以輕松地進行分發(fā)并節(jié)省你的計算資源藤树。
當導(dǎo)航欄中大多數(shù)內(nèi)容都是靜態(tài)內(nèi)容時浴滴,你可以在用戶的瀏覽器中動態(tài)地將變更內(nèi)容添加到頁面上(例如根據(jù)具體情況添加“請登錄”或者“你好,Lee”的內(nèi)容)岁钓。通過將這些動態(tài)數(shù)據(jù)進行分組升略,并與靜態(tài)內(nèi)容加以區(qū)分,可以提高Web 頁面的性能屡限,降低應(yīng)用程序需要處理的動態(tài)數(shù)據(jù)量品嚣。這樣可以提高可伸縮性,并最終提高可用性囚霸。
保持系統(tǒng)高可用需要消除系統(tǒng)中的風(fēng)險腰根。當系統(tǒng)發(fā)生故障時,通常我們已經(jīng)在這之前將故障原因確定為了風(fēng)險拓型。因此额嘿,確定風(fēng)險是提高可用性的一個重要方法。所有的系統(tǒng)中都存在以下這些風(fēng)險:
存在系統(tǒng)崩潰的風(fēng)險
存在數(shù)據(jù)庫崩潰的風(fēng)險
存在返回結(jié)果不正確的風(fēng)險
存在網(wǎng)絡(luò)連接失敗的風(fēng)險
存在新部署的軟件功能出現(xiàn)故障的風(fēng)險
保持系統(tǒng)高可用需要消除風(fēng)險劣挫。但是當系統(tǒng)變得越來越復(fù)雜時册养,消除所有風(fēng)險也變得越來越不可能實現(xiàn)。保持一個大型系統(tǒng)高可用压固,更多的是來管理系統(tǒng)的風(fēng)險球拦,知道這些風(fēng)險是什么,哪些風(fēng)險是可接受的帐我,以及你能夠做什么來緩和風(fēng)險坎炼。
我們稱之為風(fēng)險管理,它是構(gòu)建高可用系統(tǒng)的核心內(nèi)容拦键。
風(fēng)險管理中的一個部分是風(fēng)險緩和谣光。風(fēng)險緩和指的是當問題發(fā)生時,我們知道如何去盡可能降低問題所帶來的影響芬为。緩和意味著即使當服務(wù)和資源不可用時萄金,依然盡可能確保你的系統(tǒng)以最好的、最完整的狀態(tài)工作媚朦。風(fēng)險緩和需要考慮哪些事情可能會出錯氧敢,并且立即制訂相應(yīng)的計劃,以便當問題發(fā)生時能夠提供相應(yīng)的解決方案询张。
示例:風(fēng)險緩和——一個沒有搜索功能的網(wǎng)上商店
假設(shè)有一個售賣T 恤的網(wǎng)上商店孙乖。它是一個很常見的在線商店,你可以在它的首頁上瀏覽T 恤,跳轉(zhuǎn)到其他頁面查看不同的T 恤分類的圆,并且可以搜索指定風(fēng)格和類型的T 恤鼓拧。
為了實現(xiàn)搜索的功能半火,通常這類網(wǎng)上商店需要調(diào)用一個獨立的搜索引擎越妈,這可能是一個單獨的服務(wù),或者甚至由第三方的搜索服務(wù)提供钮糖。
但是梅掠,因為搜索功能是一個獨立的功能,你的系統(tǒng)就存在搜索服務(wù)不可用的風(fēng)險店归。你的風(fēng)險管理計劃需要確定出該問題阎抒,并且將“搜索引擎失敗”列為風(fēng)險之一。
如果沒有風(fēng)險緩和計劃消痛,當搜索服務(wù)失敗時且叁,可能會產(chǎn)生一個錯誤頁面,或者返回不正確或無效的結(jié)果——不管怎樣秩伞,它都會帶來很差的用戶體驗逞带。
這個示例中的風(fēng)險緩和計劃可能是這樣的:
我們知道最受歡迎的T 恤是紅色條紋T 恤,60% 訪問網(wǎng)站的用戶最終都停留在(并很可能最后會購買)這個產(chǎn)品上纱新。因此展氓,如果搜索服務(wù)停止了,我們可以顯示一個“很抱歉”的頁面脸爱,下方是我們最受歡迎的T 恤列表遇汞,其中就包括紅色條紋T 恤。
這會鼓勵遇到這個錯誤頁面的用戶簿废,繼續(xù)瀏覽別人曾經(jīng)感興趣的T 恤空入。
此外,我們還可以顯示一個“下一次購買享受10% 折扣”的優(yōu)惠券族檬,這樣就可以鼓勵之前沒有進行購買的用戶歪赢,在搜索服務(wù)恢復(fù)正常后,繼續(xù)回到我們的網(wǎng)站上進行購買导梆。
示例演示了什么是風(fēng)險緩和轨淌,而確認風(fēng)險、確定該如何處理風(fēng)險看尼,以及如何實現(xiàn)這些緩和措施的過程則被稱為風(fēng)險管理递鹉。
風(fēng)險管理經(jīng)常會暴露應(yīng)用程序中未知的、需要立即修復(fù)的問題藏斩。它還可以用來處理已知的故障問題躏结,減少故障恢復(fù)時間或者降低嚴重性。
可用性和風(fēng)險管理息息相關(guān)狰域。構(gòu)建一個高可用的系統(tǒng)媳拴,主要就是要考慮如何管理風(fēng)險黄橘。
除非你看到問題發(fā)生,否則你不會知道應(yīng)用程序中存在著問題屈溉。你應(yīng)當確保對應(yīng)用程序進行了適當?shù)谋O(jiān)控塞关,以便可以從外部和內(nèi)部兩個視角來觀察應(yīng)用程序的運行狀況。
監(jiān)控的程度取決于應(yīng)用程序的特點和要求子巾,但是通常必須具備以下這些監(jiān)控帆赢。
監(jiān)控服務(wù)器的健康狀況,并且確保它們始終在有效運行线梗。
監(jiān)控系統(tǒng)配置的變化椰于,以便確定它們對應(yīng)用程序的影響。
深入了解你的應(yīng)用程序和服務(wù)仪搔,確保它們按照預(yù)期運行瘾婿。
從用戶的角度來實時檢測應(yīng)用程序的運行情況,以便在用戶真正發(fā)現(xiàn)問題之前發(fā)現(xiàn)它們烤咧。
當問題發(fā)生時通知相關(guān)人員偏陪,以便使問題可以得到快速有效的解決,將對用戶的影響降低到最小髓削。
如今市面上有許多非常優(yōu)秀的監(jiān)控系統(tǒng)竹挡,包括免費和付費的服務(wù)。我個人推薦NewRelic立膛,它提供了之前提到的所有監(jiān)控和報警能力揪罕。作為一款軟件即服務(wù)(SaaS)的軟件,它能夠支持任何規(guī)模的應(yīng)用系統(tǒng)的監(jiān)控需求宝泵。當你對應(yīng)用程序和服務(wù)進行監(jiān)控之后好啰,請開始尋找它們的運行趨勢。當你明確了一定的趨勢之后儿奶,可以開始尋找一些異常值框往,將它們作為可能存在的可用性問題。你可以利用這些異常值闯捎,在系統(tǒng)發(fā)生故障之前通過監(jiān)控工具來發(fā)送警報椰弊。除此之外,你還可以在系統(tǒng)增長過程中時刻進行跟蹤瓤鼻,確北妫可伸縮性計劃的實施。
你應(yīng)當為服務(wù)間通信建立內(nèi)部的茬祷、私有的運行目標清焕,并持續(xù)對它們進行監(jiān)控。通過這種方式,當出現(xiàn)任何與性能或者可用性相關(guān)的問題時秸妥,你都可以快速診斷出哪個服務(wù)或者系統(tǒng)出現(xiàn)了問題滚停,并定位問題的原因。此外粥惧,你可以發(fā)現(xiàn)一些“熱點”——即性能超出預(yù)期的地方键畴,以及針對這些問題制訂相應(yīng)的開發(fā)計劃。
要點5 :以預(yù)測和確定的方式來應(yīng)對可用性問題
如果你對監(jiān)控中所發(fā)生的問題置之不理影晓,那么監(jiān)控系統(tǒng)就毫無用處镰吵。這意味著當問題發(fā)生時必須要發(fā)出報警檩禾,這樣你才能有所行動挂签。除此之外,你應(yīng)當建立整個團隊都遵循的流程盼产,幫助診斷問題饵婆,并輕松修復(fù)常見的故障問題。
例如戏售,如果某個系統(tǒng)無法響應(yīng)侨核,你可能會有一系列措施來解決。這其中可能包括運行一個測試來診斷問題原因灌灾,重啟一個已知會導(dǎo)致系統(tǒng)無法響應(yīng)的守護進程搓译,或者當其他手段都失敗時重啟整個服務(wù)器。為常見的故障問題提供標準化流程可以降低系統(tǒng)不可用的時間锋喜。此外些己,它們還可以提供更多有用的診斷信息,幫助工程師團隊找到常見問題的根本原因嘿般。
當觸發(fā)某個服務(wù)的報警時段标,該服務(wù)的負責(zé)人必須是第一個被通知到的。畢竟炉奴,他們負責(zé)修復(fù)自己服務(wù)中的所有問題逼庞。但是,其他與之緊密相關(guān)或依賴的團隊也應(yīng)當收到報警信息瞻赶。例如赛糟,如果某個團隊使用了一個特殊服務(wù),他們希望知道該服務(wù)什么時候出現(xiàn)故障砸逊,從而在問題發(fā)生時能夠更加主動地保證自己的系統(tǒng)不受影響璧南。
這些標準的流程和辦法應(yīng)當被寫進支持手冊中,團隊中每個負責(zé)人人手一份痹兜。這本支持手冊還應(yīng)該包含相關(guān)系統(tǒng)和服務(wù)的聯(lián)系人列表穆咐,以及當無法用簡單手段解決問題時,需要上報問題的聯(lián)系人列表。
所有這些流程对湃、辦法以及支持手冊都應(yīng)該提前準備好崖叫,以便當服務(wù)出現(xiàn)問題時,值班人員能準確知道如何在不同的情況下進行操作拍柒,快速恢復(fù)服務(wù)心傀。這些流程和辦法之所以非常有效,是因為故障通常都發(fā)生在一些不太方便的時間點拆讯,例如午夜或者周末這些效率比較低下的時間脂男。這些建議可以幫助你的團隊更聰明、更安全地將系統(tǒng)恢復(fù)到可運行狀態(tài)种呐。
沒人能夠預(yù)測到可用性問題在什么地方宰翅、什么時間發(fā)生。但是你可以假設(shè)它們會發(fā)生爽室,尤其是當你的系統(tǒng)面臨越來越多的用戶需求汁讼,變得越來越復(fù)雜的時候。提前做好處理可用性問題的準備阔墩,是降低問題出現(xiàn)概率和嚴重性的最佳方法嘿架。
本文選自《可伸縮架構(gòu):面向增長應(yīng)用的高可用》,點此鏈接可在博文視點官網(wǎng)查看此書啸箫。
想及時獲得更多精彩文章耸彪,可在微信中搜索“博文視點”或者掃描下方二維碼并關(guān)注。