服務(wù)可用性的一知半解
談到高并發(fā)和高可用往往引起很多人的興趣,有時候成為框架選擇的噱頭。實(shí)際上,它們往往和框架關(guān)系不大,而是跟架構(gòu)息息相關(guān)。在很多時候,老碼農(nóng)會直面一個問題:
“系統(tǒng)的服務(wù)可用性是多少?是怎么得來?”
但在思考這個問題之前,先要澄清一個概念,那就是——
什么是服務(wù)可用性
可用性就是一個系統(tǒng)處在可工作狀態(tài)的時間的比例,這通常被描述為任務(wù)可行率。數(shù)學(xué)上來講,相當(dāng)于1減去不可用性。——wiki 百科
相應(yīng)的,我們的軟件系統(tǒng)處于可工作的時間比例,就是服務(wù)的可用性,也就是說,服務(wù)可用性可以描述為一個百分比的數(shù)值。我們經(jīng)常用這個SLO(service-level objective ,服務(wù)級目標(biāo))來代表服務(wù)可用性,至于SLO,SLA,SLI 等概念之間的差異,這里暫不做深入討論。
SLO用數(shù)字來定義可用性對于特定服務(wù)的意義,來表示服務(wù)幾乎總是活著,總是處于可以快速運(yùn)行的狀態(tài)。制定SLO是根據(jù)如下:
絕大多數(shù)軟件服務(wù)和系統(tǒng)的目標(biāo)應(yīng)該是近乎完美的可用性,而不是完美的可用性。服務(wù)可用性一般是99.999% 或99.99% ,而不是100%,因?yàn)橛脩魺o法區(qū)分服務(wù)是100% 可用和不“完美”可用之間的區(qū)別。在用戶和服務(wù)之間還有許多其他的系統(tǒng),例如筆記本電腦、家庭 WiFi、互聯(lián)網(wǎng)等等 ,這些系統(tǒng)的可用性遠(yuǎn)遠(yuǎn)低于100% 。因此,99.99% 和100% 之間的邊際差異在其他不可用性的噪音中丟失了,并且,即使為增加最后一部分可用性付出了巨大努力,用戶也可能沒有從中獲得任何好處。
很多云服務(wù)的目標(biāo)是向用戶提供99.99% 的可用性(就是我們常說的“四個9”)。一些服務(wù)在外部承諾較低的數(shù)字,但在內(nèi)部可能設(shè)定了99.99% 的目標(biāo)。作為SLA,這個嚴(yán)格的目標(biāo)描述了用戶在違反合同之前對服務(wù)性能不滿意的情況,因?yàn)檐浖?wù)的首要目標(biāo)是讓用戶滿意。對于許多服務(wù),99.99% 的內(nèi)部目標(biāo)代表了平衡成本、復(fù)雜性和可用性的最佳位置。
服務(wù)可用性解讀
服務(wù)可用性是中斷頻率和持續(xù)時間的函數(shù)。它是通過以下方式衡量的: * 停機(jī)頻率,或者是它的倒數(shù): MTTF (平均停機(jī)時間)。* 持續(xù)時間,使用 MTTR (平均修復(fù)時間)。持續(xù)時間根據(jù)用戶的經(jīng)歷定義: 從故障開始持續(xù)到正常行為恢復(fù)。
因此,可用性在數(shù)學(xué)上定義為使用適當(dāng)單位的 MTTF / (MTTF + MTTR)。
四個9的服務(wù)可用性可能是很多軟件系統(tǒng)的目標(biāo),如何達(dá)到這一目標(biāo)呢?需要先明確一下導(dǎo)致服務(wù)不可用的來源。服務(wù)不可用有兩個主要來源: 服務(wù)本身的問題和服務(wù)的關(guān)鍵依賴的問題。關(guān)鍵依賴是指如果出現(xiàn)故障,就會導(dǎo)致服務(wù)相應(yīng)故障的依賴項(xiàng)。
關(guān)鍵依賴
服務(wù)的可用性不能超過其所有關(guān)鍵依賴關(guān)系的交集。如果服務(wù)的目標(biāo)是提供99.99% 的可用性,那么所有的關(guān)鍵依賴項(xiàng)必須遠(yuǎn)遠(yuǎn)超過99.99% 的可用性。據(jù)說在谷歌內(nèi)部,使用這樣一個經(jīng)驗(yàn)法則: 因?yàn)槿魏畏?wù)都有幾個關(guān)鍵依賴項(xiàng),以及自身的特殊問題,關(guān)鍵依賴必須提供一個與服務(wù)相關(guān)的額外9% 的可用性(這里為99.999%) 。
如果有一個關(guān)鍵依賴,一個相對常見的挑戰(zhàn)是沒有提供足夠的可用性,就必須采取措施來增加依賴項(xiàng)的有效可用性(例如,通過緩存、限流、優(yōu)雅降級等等)。
降低期望
從數(shù)學(xué)上看,服務(wù)的可用性不能超過其事件頻率乘以其檢測和恢復(fù)時間。例如,每年有4次完全宕機(jī),每次持續(xù)15分鐘,結(jié)果總共是60分鐘。即使該服務(wù)在這一年中剩下的時間里都運(yùn)行良好,99.99% 的可用性(每年停機(jī)時間不超過53分鐘)也是沒有達(dá)的。
如果服務(wù)被依賴于無法提供相應(yīng)水平的可用性級別,那么就應(yīng)該努力糾正這種情況,可以通過增加自身服務(wù)的可用性等級,或者如前所述的增加緩解措施。降低期望值(即公布的可用性)也是一種選擇,而且往往是正確的選擇: 向相關(guān)服務(wù)明確表示,它應(yīng)該重新設(shè)計系統(tǒng)以彌補(bǔ)我們服務(wù)可用性,或者降低自己的目標(biāo)。如果不糾正或解決這種差異,可用性將無法達(dá)到要求。
服務(wù)可用性的計算
考慮一個目標(biāo)可用性為99.99% 的示例服務(wù),并處理依賴項(xiàng)和停機(jī)響應(yīng)的需求。
一個例子
假設(shè)這個99.99% 的可用服務(wù)具有以下特征:
- 每年一次大停機(jī)和三次小停機(jī)。這些數(shù)字聽起來很高,但是99.99% 的可用性目標(biāo)確實(shí)意味著每年有20到30分鐘的大范圍停機(jī)和幾次短暫的部分停機(jī)。這里的假設(shè)是: 單個分片的失敗并不被認(rèn)為是整個系統(tǒng)的失敗,總體可用性是根據(jù)分片可用性的加權(quán)和來計算的。
- 有五個獨(dú)立關(guān)鍵依賴, 服務(wù)可用性為99.999%。
- 這五個相互獨(dú)立的碎片,不能相互轉(zhuǎn)移。
- 所有變更逐個進(jìn)行,每次一個分片。
那么,本年度服務(wù)中斷的總預(yù)算為每年525,600分鐘的的0.01%或53分鐘(以每年365天為基礎(chǔ))。分配給關(guān)鍵依賴的服務(wù)中斷預(yù)算是5個525,600分鐘的0.001%,即525,600分鐘的0.005% 或26分鐘??紤]到關(guān)鍵依賴的服務(wù)中斷,該服務(wù)的中斷時間預(yù)算為53-26=27分鐘。
進(jìn)一步,預(yù)計停機(jī)次數(shù)為4次(1次完全停機(jī),3次停機(jī)僅影響一個分片), 預(yù)期服務(wù)中斷的總影響: (1 x 100%) + (3 x 20%)= 1.6。那么,可用于檢測和從中斷恢復(fù)的時間為27 / 1.6 = 17分鐘。如果監(jiān)控和告警的時間是2分鐘,值班人員調(diào)查警報的時間為5分鐘的話,則有效解決問題的剩余時間是 10分鐘。
提高可用性的方向
仔細(xì)研究這些數(shù)字,有三個主要的因素可以使服務(wù)更可靠。
- 透過流程、測試、設(shè)計review等手段,減少宕機(jī)的次數(shù)。
- 通過分片、地理隔離、優(yōu)雅降級或客戶隔離,縮小停機(jī)范圍。
- 縮短恢復(fù)時間ーー透過監(jiān)控、一鍵式回滾等。
可以在這三個方向之間進(jìn)行權(quán)衡,以便實(shí)現(xiàn)更加容易。例如,如果17分鐘的 MTTR 很難實(shí)現(xiàn),那么應(yīng)該將精力集中在減少平均停用的范圍上。
服務(wù)可用性之依賴嵌套
一個不經(jīng)意的推斷,依賴鏈中的每個額外鏈接都需要增加額外的可用性等級么?例如,二級依賴需要兩個額外的9,三級依賴需要三個額外的9,以此類推。
這種推論是不正確的,它基于依賴關(guān)系層次結(jié)構(gòu),即在每個級別上具有常量扇出的樹 具有許多獨(dú)立關(guān)鍵依賴的高可用性服務(wù)系統(tǒng)顯然是不現(xiàn)實(shí)的。
無論在依賴項(xiàng)樹中出現(xiàn)在哪里,關(guān)鍵依賴項(xiàng)本身都可能導(dǎo)致整個服務(wù)(或服務(wù)分片)失敗。因此,如果給定的組件A表現(xiàn)為幾個服務(wù)的依賴項(xiàng),那么 A應(yīng)該只計算一次,因?yàn)闊o論有多少中間的服務(wù)受到影響,A的故障終將導(dǎo)致服務(wù)的故障。
正確的依賴計算可能是這樣的:
- 如果一個服務(wù)具有N個唯一的關(guān)鍵依賴項(xiàng),那么每個依賴對服務(wù)導(dǎo)致的不可用性貢獻(xiàn)1 / N,而不管它在層次結(jié)構(gòu)中的深度如何。
- 即使它在依賴項(xiàng)層次結(jié)構(gòu)中出現(xiàn)多次,每個依賴也只計算一次。
例如,假設(shè)服務(wù)b 的故障預(yù)算為0.01% 。服務(wù)擁有者愿意花一半的預(yù)算在他們自己的 bug 和損失上,另一半花在關(guān)鍵依賴上。如果服務(wù)有 N個這樣的依賴項(xiàng),每個依賴項(xiàng)接收剩余故障預(yù)算的1 / N。典型的服務(wù)通常有5到10個關(guān)鍵依賴項(xiàng),因此每個服務(wù)的失敗率只有服務(wù)b 的十分之一或二十分之一。因此,根據(jù)一般經(jīng)驗(yàn),服務(wù)的關(guān)鍵依賴項(xiàng)必須增加額外的可用性。
服務(wù)可用性之故障預(yù)算
一般地,使用故障預(yù)算來平衡可用性和創(chuàng)新速度。這個預(yù)算定義了在一段時間內(nèi)(通常是一個月)服務(wù)可接受的故障水平。故障預(yù)算只是1減去服務(wù)的 SLO,因此,99.99% 可用的服務(wù)是故障為0.01% 的“預(yù)算”。只要服務(wù)沒有花費(fèi)當(dāng)月的故障預(yù)算,開發(fā)團(tuán)隊就可以在合理范圍內(nèi)自由地發(fā)布新特性、更新等等。
如果使用了故障預(yù)算,除了緊急安全修復(fù)和解決最初導(dǎo)致違規(guī)的更改之外,服務(wù)可能將凍結(jié)變更。直到服務(wù)在預(yù)算中贏得了空間,或者時間重置。使用 SLOs 滑動窗口,因此故障預(yù)算逐漸增加。對于 SLO 大于99.99% 的成熟服務(wù),每季度重置預(yù)算是適當(dāng)?shù)模驗(yàn)樵试S的停機(jī)時間很小。
故障預(yù)算提供了一個共同的、數(shù)據(jù)驅(qū)動的機(jī)制來評估發(fā)布風(fēng)險,從而消除了可能在運(yùn)維團(tuán)隊和產(chǎn)品開發(fā)團(tuán)隊之間產(chǎn)生的結(jié)構(gòu)性緊張。故障預(yù)算還提供了一個共同的目標(biāo),在不“超出預(yù)算”的情況下實(shí)現(xiàn)更快的創(chuàng)新和更多的發(fā)布。
提高服務(wù)可用性:減少關(guān)鍵依賴
現(xiàn)在,可以重點(diǎn)討論服務(wù)的依賴關(guān)系,如何進(jìn)行設(shè)計以減少并最小化關(guān)鍵依賴。
關(guān)于關(guān)鍵依賴
一般的,任何關(guān)鍵部件的可用性必須是整個系統(tǒng)目標(biāo)的10倍。因此,在一個理想的世界中,目標(biāo)是使盡可能多的組件成為非依賴的。這樣做意味著組件可以堅持較低的可靠性標(biāo)準(zhǔn),獲得創(chuàng)新和承擔(dān)風(fēng)險的自由。
減少關(guān)鍵依賴性的最基本和最明顯的策略是盡可能消除 SPOFs (單點(diǎn)故障)。較大的系統(tǒng)應(yīng)該能夠在沒有任何非關(guān)鍵依賴項(xiàng)或 SPOF 的給定組件的情況下可以可接受地運(yùn)行。
實(shí)際上,您可能無法擺脫所有關(guān)鍵的依賴關(guān)系,但是您可以遵循一些圍繞系統(tǒng)設(shè)計的最佳實(shí)踐來優(yōu)化可靠性。雖然這樣做并不總是可行的,但是如果你在設(shè)計和規(guī)劃階段計劃可靠性,而不是在系統(tǒng)運(yùn)行并影響實(shí)際用戶之后,那么實(shí)現(xiàn)系統(tǒng)可靠性就會更容易和更有效。
當(dāng)考慮一個新的系統(tǒng)或服務(wù)時,當(dāng)重構(gòu)或改進(jìn)一個現(xiàn)有系統(tǒng)或服務(wù)時,一個架構(gòu)/設(shè)計評審可以識別出內(nèi)部與外部的依賴。如果服務(wù)使用的是共享基礎(chǔ)設(shè)施(例如,多個用戶可見產(chǎn)品使用的基礎(chǔ)數(shù)據(jù)庫服務(wù)) ,要考慮該基礎(chǔ)設(shè)施是否得到正確使用。明確地將共享基礎(chǔ)結(jié)構(gòu)的所有者確定為附加的利益相關(guān)者。另外,要注意不要讓依賴關(guān)系超載,小心地與這些依賴關(guān)系的所有者協(xié)調(diào)工作。
有時,產(chǎn)品或服務(wù)取決于公司無法控制的因素,例如,代碼庫、第三方提供的服務(wù)或數(shù)據(jù),要識別這些因素可以減少它們帶來的不可預(yù)測性。
冗余和隔離
通過將依賴設(shè)計為具有多個獨(dú)立實(shí)例來減輕對關(guān)鍵依賴的依賴。例如,如果在一個實(shí)例中存儲的數(shù)據(jù)提供了該數(shù)據(jù)99.9% 的可用性,那么在三個分布的實(shí)例中存儲三個副本提供了9個9的理論可用性級別。
在現(xiàn)實(shí)世界中,相關(guān)性永遠(yuǎn)不會為零,因此實(shí)際可用性不會接近9個9,而是遠(yuǎn)遠(yuǎn)高于3個9。如果一個系統(tǒng)或服務(wù)是“廣泛分布的” ,地理上的分離并不總是不相關(guān)的。在鄰近地點(diǎn)使用多個系統(tǒng),可能比在較遠(yuǎn)地點(diǎn)使用同一個系統(tǒng)更好。
類似地,向一個集群中的一個服務(wù)器池發(fā)送 RPC可以提供99.9% 的可用性,但是向三個不同的服務(wù)器池發(fā)送三個并發(fā) RPC 并接受到達(dá)的第一個響應(yīng),這樣有助于將可用性提高到遠(yuǎn)遠(yuǎn)超過三個9的級別。如果服務(wù)器池與 RPC 發(fā)送方的距離大致相等,那么這種策略還可以減少延遲。
故障切換與回滾
一個的基本經(jīng)驗(yàn)是,當(dāng)必須人工在線引發(fā)故障切換時,可能已經(jīng)超出了故障預(yù)算。最好進(jìn)行故障的安全切換,如果出現(xiàn)問題,這些軟件可以自動隔離。在無法實(shí)現(xiàn)的情況下,可以執(zhí)行自動腳本。同樣,如果問題依賴于某一個人來檢查,那么滿足SLO 的機(jī)會會很小。
將人引入緩解計劃大大增加了 SLO 的風(fēng)險,需要構(gòu)建方便、快速而可靠回滾的系統(tǒng)。隨著系統(tǒng)逐漸成熟,并且對檢測問題的監(jiān)視獲得了信心,就可以通過設(shè)計系統(tǒng)自動觸發(fā)安全回滾來降低 MTTR。
在可能的情況下,將依賴項(xiàng)設(shè)計為異步的,而不是同步的,這樣它們就不會意外地變得非常重要。如果服務(wù)等待來自其非關(guān)鍵依賴項(xiàng)之一的 RPC 響應(yīng),并且該依賴項(xiàng)的延遲會大大增加,那么這種延遲將不必要地影響父服務(wù)的延遲。通過將 RPC 調(diào)用設(shè)置為非關(guān)鍵的異步依賴項(xiàng),可以將父服務(wù)的延遲與依賴項(xiàng)的延遲解耦。雖然異步性可能會使代碼和基礎(chǔ)結(jié)構(gòu)復(fù)雜化,但這種權(quán)衡可能是值得的。
檢查所有可能的失效模式
檢查每個組件和依賴項(xiàng),并確定其故障的影響。以下問題可能是一些方向:
- 如果其中一個依賴項(xiàng)失敗,服務(wù)能否繼續(xù)以降級模式提供服務(wù)?換句話說,為優(yōu)雅的降級而設(shè)計。
- 如何處理在不同情況下依賴項(xiàng)不可用的問題?在服務(wù)啟動時?在運(yùn)行期間?
設(shè)計和實(shí)現(xiàn)一個健壯的測試環(huán)境,確保每個依賴項(xiàng)都有自己的測試覆蓋率,并且使用專門針對環(huán)境的用例進(jìn)行測試。以下是一些推薦的測試策略:
- 使用集成測試執(zhí)行故障注入ーー驗(yàn)證系統(tǒng)能否在任何依賴關(guān)系發(fā)生故障時幸存下來。
- 進(jìn)行災(zāi)難測試以識別弱點(diǎn)或隱藏的依賴關(guān)系。記錄后續(xù)行動,以糾正發(fā)現(xiàn)的bug。
- 故意讓系統(tǒng)過載,看看它是如何退化的。無論如何,系統(tǒng)對負(fù)載的響應(yīng)都將被測試; 最好是自己執(zhí)行這些測試,而不是將負(fù)載測試留給用戶。
容量規(guī)劃
確保每個依賴項(xiàng)都得到了正確的供給,如果成本可以接受,就過度供給。如果可能,將依賴項(xiàng)的配置標(biāo)準(zhǔn)化,以限制子系統(tǒng)之間的不一致性,并避免一次性的故障模式。
檢測、故障排除和診斷問題要盡可能簡單,有效的監(jiān)測是能夠及時發(fā)現(xiàn)問題的關(guān)鍵組成部分。診斷具有嚴(yán)重依賴關(guān)系的系統(tǒng)是困難的,但總是有一個不需要操作員就可以減輕故障的方案。
期待隨著規(guī)模而來的變化,當(dāng)在一臺機(jī)器上以二進(jìn)制文件開始的服務(wù)在更大的規(guī)模上部署時,可能會有許多明顯或不明顯的依賴關(guān)系。每一個規(guī)模的數(shù)量級都會暴露出新的瓶頸, 不僅僅是自己服務(wù),還有所依賴的服務(wù)。考慮一下,如果依賴項(xiàng)不能像所需要的那樣快速擴(kuò)展,將會發(fā)生什么。
還要注意,系統(tǒng)依賴關(guān)系會隨著時間的推移而發(fā)展,并且依賴關(guān)系的列表可能會隨著時間的推移而增長。在基礎(chǔ)設(shè)施方面,一個典型的設(shè)計是建立一個不需要重大變更就可以擴(kuò)展到初始目標(biāo)負(fù)載10倍的系統(tǒng)。
結(jié)束語
服務(wù)的用性并不高深莫測,它只是一個百分比的數(shù)字。服務(wù)可用性的指標(biāo)(例如99.99%)往往令人不安,但并非不可實(shí)現(xiàn)。提供超過四個9的服務(wù)可用性,不是通過超出常人的智慧,而是通過不斷地完善規(guī)則形成最佳實(shí)踐,并且全面應(yīng)用。