“系統(tǒng)-管理員” 的比例通??梢宰鳛橐环N理解大規(guī)模服務(wù)的管理開(kāi)銷(xiāo)的粗略度量方式。 對(duì)于那些規(guī)模越小、 越缺乏自動(dòng)化的服務(wù)來(lái)說(shuō), 這個(gè)比率越低, 可能低至2:1, 而對(duì)于那些業(yè)界領(lǐng)先、高度自動(dòng)化的服務(wù)來(lái)說(shuō),該比率可高達(dá) 2500:1。 盡管自動(dòng)化管理確實(shí)很重要,但最重要的還是服務(wù)本身。 服務(wù)是否能夠高效地進(jìn)行自動(dòng)化? 是否是運(yùn)維友好的(operations-friendly)? 運(yùn)維友好的服務(wù)幾乎不需要人工干預(yù),同時(shí)除了極個(gè)別最難解的故障外都可以在無(wú)運(yùn)維人員干預(yù)的情況下被自動(dòng)檢測(cè)到并恢復(fù)。
導(dǎo)引
本文總結(jié)了用于設(shè)計(jì)和開(kāi)發(fā)運(yùn)維友好的服務(wù)的一系列最佳實(shí)踐。大規(guī)模服務(wù)的設(shè)計(jì)和部署目前仍是一個(gè)快速發(fā)展中的領(lǐng)域。因此這樣的一個(gè)最佳實(shí)踐列表隨著時(shí)間的推移也會(huì)不斷的演化。我們的目的是幫助人們:
- 快速交付運(yùn)維友好的服務(wù)
- 遠(yuǎn)離那些非運(yùn)維友好的服務(wù)可能帶來(lái)的: 凌晨的電話報(bào)警, 充滿了客戶(hù)抱怨聲的惱人會(huì)議
Bill Hoffman給本文貢獻(xiàn)了很多最佳實(shí)踐, 以及三條很值得在一開(kāi)始就考慮的簡(jiǎn)單信條,這三條原則形成了貫穿后面大多數(shù)討論的主線:
- Expect failures。 一個(gè)組件可能在任意時(shí)間掛掉或停止工作。 它所依賴(lài)的組件也可能在任何時(shí)間掛掉或停止工作。會(huì)發(fā)生網(wǎng)絡(luò)故障,磁盤(pán)空間耗盡等。需要優(yōu)雅地處理所有的故障。
- Keep things simple。復(fù)雜導(dǎo)致問(wèn)題產(chǎn)生。簡(jiǎn)單的東西更容易做正確。避免不必要的依賴(lài)。 安裝應(yīng)該很簡(jiǎn)單。 單臺(tái)服務(wù)器的故障應(yīng)該對(duì)集群其它部分沒(méi)有影響。
- Automate everything。人會(huì)犯錯(cuò), 人需要睡覺(jué), 人會(huì)忘記東西。自動(dòng)化的過(guò)程是可測(cè)試的,可固定的, 因此最終更可靠。 盡可能地將所有地方自動(dòng)化。
目錄
本文被分成如下 10 小節(jié),每小節(jié)都覆蓋了設(shè)計(jì)和部署運(yùn)維友好的服務(wù)所需遵守的不同方面的要求:
- 總體服務(wù)設(shè)計(jì)
- 自動(dòng)化配置和管理設(shè)計(jì)(designing for automation and provisioning)
- 依賴(lài)管理
- 發(fā)布周期和測(cè)試
- 硬件選型和標(biāo)準(zhǔn)化
- 運(yùn)維和容量規(guī)劃
- 審計(jì)監(jiān)控和報(bào)警
- 優(yōu)雅降級(jí)和準(zhǔn)入控制
- 客戶(hù)和媒體溝通計(jì)劃
- 客戶(hù)自配置和自助(customer self provisioning and self help)
總體服務(wù)設(shè)計(jì)
我們相信, 80%的運(yùn)維問(wèn)題源自設(shè)計(jì)和開(kāi)發(fā)。 因此服務(wù)總體設(shè)計(jì)這一節(jié)是篇幅最多,也最重要的一節(jié)。系統(tǒng)發(fā)生故障時(shí),很自然會(huì)先去檢查運(yùn)維過(guò)程,因?yàn)槟鞘菃?wèn)題實(shí)際發(fā)生的地方。但是,大多數(shù)的運(yùn)維問(wèn)題要么是設(shè)計(jì)或開(kāi)發(fā)導(dǎo)致的,要么是最好在設(shè)計(jì)和開(kāi)發(fā)階段解決。
在下面的小節(jié)中有一個(gè)共識(shí):嚴(yán)格地區(qū)分開(kāi)發(fā)、 測(cè)試和運(yùn)維, 這在服務(wù)的世界里并不是最有效的工作方式。我們?cè)诤芏喾?wù)那里看到低成本的管理跟開(kāi)發(fā)、測(cè)試和運(yùn)維團(tuán)隊(duì)間合作的緊密程度密切相關(guān)(注:有點(diǎn)DevOps的味道了)。
除了本節(jié)討論的最佳實(shí)踐, 下一節(jié)的“自動(dòng)化管理和配置”, 對(duì)服務(wù)設(shè)計(jì)也有很大的影響。 高效的自動(dòng)化管理和配置只有在特定的服務(wù)模型上才能達(dá)成。 這是一個(gè)反復(fù)強(qiáng)調(diào)的主題:簡(jiǎn)單性是高效運(yùn)維的關(guān)鍵。 在硬件選型, 服務(wù)設(shè)計(jì),部署模型上的合理限制, 可以大大降低管理成本,提高服務(wù)可靠性。
對(duì)服務(wù)整體設(shè)計(jì)影響最大的一些運(yùn)維友好的基本原則如下:
Design for failure。
這是一個(gè)開(kāi)發(fā)由很多協(xié)作組件構(gòu)成的大型服務(wù)時(shí)的核心觀念。 哪些組件會(huì)發(fā)生故障,而且會(huì)頻繁發(fā)生故障。 一旦服務(wù)規(guī)模超過(guò) 10,000臺(tái)服務(wù)器和 50,000 個(gè)磁盤(pán)后,一天內(nèi)都會(huì)發(fā)生多次故障。 如果一個(gè)硬件故障發(fā)生后需要馬上進(jìn)行人工處理, 那么服務(wù)就根本沒(méi)辦法低成本和可靠地進(jìn)行擴(kuò)展。整個(gè)服務(wù)必須有能力在沒(méi)有人工干預(yù)的情況下在故障發(fā)生時(shí)還能繼續(xù)工作。故障恢復(fù)必須是非常簡(jiǎn)單的路徑,并且經(jīng)常對(duì)該路徑進(jìn)行測(cè)試。
Stanford 的 Armando Fox 認(rèn)為最好的測(cè)試故障路徑的方式就是從來(lái)都不去正常地停掉服務(wù),而是直接讓它掛掉。這看起來(lái)違反直覺(jué),但如果故障路徑?jīng)]有頻繁被使用的話, 在真的需要它的時(shí)候它根本就不能工作。 斯坦福的Armando Fox認(rèn)為測(cè)試故障路徑的最好方式就是從來(lái)都不正常地停掉服務(wù),而是直接讓它掛掉(Just hard-fail it)。這看起來(lái)違反直覺(jué),但如果故障路徑不常被使用的話, 那么在真的需要時(shí)它根本就不能工作。(注:現(xiàn)在看起來(lái)也不算反直覺(jué)了,已經(jīng)有公司這么做了)
冗余和故障恢復(fù)。
大型機(jī)模型需要購(gòu)買(mǎi)非常大且昂貴的服務(wù)器。 大型機(jī)具有冗余的電源、 熱插拔的 CPU、 獨(dú)特的總線結(jié)構(gòu), 在一個(gè)單一、 緊耦合的系統(tǒng)中提供了令人驚訝的 IO 吞吐量。這種方式明顯的問(wèn)題是成本高,但即使這樣, 它也不是足夠可靠。要達(dá)到 5 個(gè) 9 的可靠性,冗余是必需的。即使要達(dá)到 4 個(gè) 9,單系統(tǒng)的部署方式也是很難做到的。這個(gè)觀念已經(jīng)在業(yè)界被廣泛接受,但還是能經(jīng)??吹揭恍┎渴鹪诖嗳醯?、 非冗余數(shù)據(jù)層上的服務(wù)。
要設(shè)計(jì)一個(gè)任何組件在任何時(shí)間都可以掛掉(或者是關(guān)掉服務(wù)),但仍能滿足相應(yīng) SLA(service level agreement)的服務(wù),需要細(xì)致的工程化。要判斷是否遵循了這條設(shè)計(jì)原則, 可以采用如下方法:運(yùn)維團(tuán)隊(duì)是否愿意并且也能夠隨時(shí)關(guān)掉服務(wù)的任何一個(gè)服務(wù)器, 同時(shí)也不用等待將上面的工作負(fù)載排除?如果可以, 那么說(shuō)明服務(wù)實(shí)現(xiàn)了同步化冗余(沒(méi)有數(shù)據(jù)丟失),故障檢測(cè)和自動(dòng) failover。
作為一種設(shè)計(jì)方法,我們介紹一下常用來(lái)發(fā)現(xiàn)和糾正服務(wù)的潛在安全問(wèn)題的安全威脅模型。在安全威脅模型里,我們考慮每一種可能的安全威脅,并且針對(duì)性地給出緩解方案。同樣的方法可以用在容錯(cuò)和故障恢復(fù)的設(shè)計(jì)上。
列舉出所有可能的組件故障模式, 及其組合。對(duì)每一種故障,確保服務(wù)能夠在沒(méi)有無(wú)法接受的服務(wù)質(zhì)量損失情況下繼續(xù)運(yùn)作, 或者確定該故障的風(fēng)險(xiǎn)對(duì)這個(gè)服務(wù)是可接受的(比如, 沒(méi)有地理冗余的服務(wù)所在的數(shù)據(jù)中心掛掉了)。
一些非常不尋常的故障組合, 要處理它們?cè)诔杀旧鲜遣豢山邮艿模?可能會(huì)被認(rèn)為是不可能發(fā)生的。但是,做這種決定時(shí)要謹(jǐn)慎。 我們已多次驚訝的發(fā)現(xiàn)某些不尋常的事件的組合, 是如何頻繁發(fā)生在運(yùn)行成千上萬(wàn)的服務(wù)器每天數(shù)以百萬(wàn)計(jì)的組件故障的情況下了。 罕見(jiàn)的組合可以變得司空見(jiàn)慣。
Commodity hardware slice。
服務(wù)的所有組件都應(yīng)當(dāng)基于普通商用硬件。(注:這種模式目前已經(jīng)成為主流)
1) 由大量廉價(jià)服務(wù)器組成的大規(guī)模集群要比由少量大型服務(wù)器組成的便宜很多。
2) 服務(wù)器性能比 IO 性能的增長(zhǎng)快得多。同樣數(shù)量的磁盤(pán),小型服務(wù)器的性能更均衡。
3) 耗電量跟服務(wù)器數(shù)量是線性關(guān)系,跟時(shí)鐘頻率是三次方關(guān)系, 這使得高性能服務(wù)器運(yùn)營(yíng)成本更高。
4) 小服務(wù)器 failover 時(shí)只會(huì)影響服務(wù)整體工作負(fù)載中的一小部分。
單一版本軟件。
有兩個(gè)因素讓服務(wù)比大多數(shù)打包發(fā)行的軟件開(kāi)發(fā)成本更低,進(jìn)化更快,對(duì)于服務(wù)來(lái)說(shuō):
- 軟件只需要面向一個(gè)單一的內(nèi)部部署環(huán)境
- 之前的版本不需要像面向企業(yè)的產(chǎn)品那樣一支持就是 10 幾年
單一版本軟件相對(duì)容易為消費(fèi)者提供服務(wù),尤其是免費(fèi)提供。 但是在向非消費(fèi)者銷(xiāo)售基于訂閱的服務(wù)時(shí),這一點(diǎn)也是同等重要的。 企業(yè)已經(jīng)習(xí)慣了強(qiáng)力地影響它們的軟件提供商,并且習(xí)慣了在部署新版本時(shí)擁有完全的控制(通常是非常緩慢的)。 這抬高了運(yùn)維成本和支持成本, 因?yàn)橛泻芏喟姹拘枰С帧?br> 最經(jīng)濟(jì)型的服務(wù)不會(huì)讓客戶(hù)可以控制它們的運(yùn)行版本,同時(shí)只會(huì)保有一個(gè)版本。 控制這種單一版本軟件時(shí)需要:
- 發(fā)布要避免造成用戶(hù)體驗(yàn)發(fā)生重大改變
- 對(duì)于那些想要控制版本升級(jí)的客戶(hù)來(lái)說(shuō), 要么自己部署一套,要么切換到愿意提供多版本支持的服務(wù)商。
多租戶(hù)(Multi-tenancy)。
多租戶(hù)是指將所有公司或終端用戶(hù)都囊括在同一個(gè)沒(méi)有物理隔離的服務(wù)里,而與之相比單租戶(hù)則是指將用戶(hù)進(jìn)行分組放到獨(dú)立的集群中。 進(jìn)行多租戶(hù)的理由幾乎與單一版本軟件相同,同時(shí)也正是因?yàn)檫@樣,才可以為建立在自動(dòng)化基礎(chǔ)上的大規(guī)模服務(wù)從根本上降低成本。
通過(guò)對(duì)服務(wù)設(shè)計(jì)和運(yùn)維模型進(jìn)行限制, 可以最大化我們構(gòu)建自動(dòng)化和低成本的服務(wù)的能力。 在我們的這些目標(biāo)和應(yīng)用服務(wù)提供商或者 IT 外包商的那些目標(biāo)之間有一個(gè)明顯的區(qū)別。 那些企業(yè)通常是人力密集型的,同時(shí)更愿意運(yùn)行復(fù)雜的, 由客戶(hù)定制的配置。
一些更具體的設(shè)計(jì)運(yùn)維友好的服務(wù)的最佳實(shí)踐如下:
服務(wù)健康狀況快速檢查。
服務(wù)版的構(gòu)建驗(yàn)證測(cè)試(BVT-build/verification/test),開(kāi)發(fā)人員修改代碼后, 編譯生成新版本, 驗(yàn)證最新生成的軟件版本在功能上是否完整,主要的軟件特性是否正確。 BVT 優(yōu)點(diǎn)是時(shí)間短,驗(yàn)證了軟件的基本功能。缺點(diǎn)是該種測(cè)試的覆蓋率很低}, 這是一個(gè)可以在開(kāi)發(fā)人員的系統(tǒng)環(huán)境上運(yùn)行的嗅探性測(cè)試,確保服務(wù)沒(méi)有遭受實(shí)質(zhì)性的破壞。 不是所有的邊界條件都會(huì)被測(cè)試到,但如果這個(gè)測(cè)試通過(guò)了,代碼就可以 check in。(注:持續(xù)集成的概念)
在完整的環(huán)境里開(kāi)發(fā)。
開(kāi)發(fā)人員除了需要進(jìn)行自己模塊的單元測(cè)試,還要對(duì)包含了他們的變更后的整個(gè)服務(wù)進(jìn)行測(cè)試。 要高效的實(shí)現(xiàn)這一點(diǎn)需要支持單機(jī)部署 ,以及前面的那條最佳實(shí)踐—服務(wù)健康狀況快速檢查。
對(duì)底層組件零信任。
假定依賴(lài)組件會(huì)掛掉, 同時(shí)要確保組件能恢復(fù)并繼續(xù)提供服務(wù)。 恢復(fù)技術(shù)是與服務(wù)本身相關(guān)的,但是也有一些常用的恢復(fù)技術(shù):
1) 以只讀模式繼續(xù)訪問(wèn)緩存的數(shù)據(jù)
2) 繼續(xù)對(duì)所有用戶(hù)提供服務(wù),除了那些受故障影響的一小部分用戶(hù)
不在多個(gè)組件里實(shí)現(xiàn)同樣的功能。
要預(yù)見(jiàn)未來(lái)的交互方式是很困難的, 同時(shí)如果系統(tǒng)中存在代碼冗余的話那就需要在系統(tǒng)的多個(gè)部分中進(jìn)行修復(fù)。 服務(wù)總在快速的增長(zhǎng)和演化。 如不小心,代碼庫(kù)會(huì)迅速惡化。
不同集群之間不應(yīng)該相互影響。
大部分服務(wù)都是由位于多個(gè)機(jī)器集或子集群的相互協(xié)作的多個(gè)系統(tǒng)組成。 它們相互之間要盡可能 100%獨(dú)立,避免關(guān)聯(lián)故障。 那些全局性的服務(wù)即使具有冗余備份也是一個(gè)單點(diǎn)。 有時(shí)候這種情況可能無(wú)法避免,但是還是要盡可能把一個(gè)集群依賴(lài)的東西都放到集群里面。
允許(極少情況下的)緊急人工干預(yù)。
常見(jiàn)的場(chǎng)景是災(zāi)害后或其他緊急情況下的用戶(hù)數(shù)據(jù)遷移。 要將系統(tǒng)設(shè)計(jì)地永遠(yuǎn)不需要人工干預(yù),但是也要理解一些組合故障或者意料之外的故障發(fā)生時(shí)會(huì)需要人工干預(yù)。 這些情況會(huì)發(fā)生,同時(shí)在這些情況下的操作失誤是很多災(zāi)難性數(shù)據(jù)丟失的常見(jiàn)來(lái)源。 一個(gè)在凌晨2 點(diǎn)頂著壓力干活的 PE, 很可能犯錯(cuò)。系統(tǒng)的設(shè)計(jì)首先要讓絕大多數(shù)情況不需要 PE 干預(yù),但對(duì)于需要 PE 干預(yù)的情況,要跟 PE 一起確定預(yù)案。預(yù)案不能僅是記在文檔里的多步驟的、容易出錯(cuò)的過(guò)程, 應(yīng)該將它們寫(xiě)成腳本,在生產(chǎn)環(huán)境測(cè)試,確保可用。沒(méi)有在生產(chǎn)環(huán)境里測(cè)試過(guò)的東西是無(wú)法 work 的。
所以運(yùn)維團(tuán)隊(duì)?wèi)?yīng)該周期性地組織演習(xí)來(lái)使用這些工具。如果演習(xí)對(duì)服務(wù)可用性的風(fēng)險(xiǎn)很大,說(shuō)明對(duì)于這些工具的設(shè)計(jì)、開(kāi)發(fā)、測(cè)試的投入不夠。
保持簡(jiǎn)單和健壯。
復(fù)雜的算法和組件交互會(huì)將調(diào)試和部署等方面的困難加倍。
在大規(guī)模服務(wù)中, 故障模式的數(shù)量在進(jìn)行復(fù)雜的優(yōu)化之前就已經(jīng)夠讓人害怕的了。一個(gè)總體原則是:超過(guò)一個(gè)數(shù)量級(jí)的改進(jìn)才值得考慮,只有幾個(gè)百分點(diǎn)甚至更少的改進(jìn)是不值得去做的。
在所有層執(zhí)行準(zhǔn)入控制。
所有好系統(tǒng)都會(huì)在入口設(shè)計(jì)有準(zhǔn)入控制。這遵循了一個(gè)長(zhǎng)期以來(lái)被人們所接受的原則: 與繼續(xù)接受新任務(wù)導(dǎo)致系統(tǒng)震蕩相比,更好的方式是不要讓更多任務(wù)進(jìn)入過(guò)載的系統(tǒng)。在服務(wù)入口處通常都有某種形式的流控或準(zhǔn)入控制,但是在所有重要組件的邊界上也都應(yīng)該有準(zhǔn)入控制。
負(fù)載特點(diǎn)的變化常常會(huì)導(dǎo)致某個(gè)子組件過(guò)載,盡管整體服務(wù)負(fù)載可能還在一個(gè)可以接受的水平上。 下面提到的“big red switch” 就是一種在過(guò)載情況下的優(yōu)雅降級(jí)方式。 總體原則是嘗試優(yōu)雅降級(jí)而不是讓系統(tǒng)直接掛掉,在所有用戶(hù)受到影響之前阻止進(jìn)入。
對(duì)服務(wù)進(jìn)行分區(qū)(Partition the service)。
分區(qū)應(yīng)該是細(xì)粒度的,無(wú)限可調(diào)的,并且不綁定在任何現(xiàn)實(shí)實(shí)體上(比如人, 團(tuán)體等)。 比如如果按照公司進(jìn)行劃分,那么一個(gè)規(guī)模很大的公司就會(huì)超過(guò)單個(gè)分區(qū)的大小。 再比如如果按照人名前綴進(jìn)行劃分,那么最后那些以 P 開(kāi)頭的, 將無(wú)法采用單個(gè)服務(wù)器存下它們。 我們推薦用一個(gè)中間層的查找表把細(xì)粒度實(shí)體(典型的如用戶(hù))映射到相應(yīng)的數(shù)據(jù)管理系統(tǒng)。 然后這些細(xì)粒度分區(qū)就可以在服務(wù)器間自由移動(dòng)。
理解網(wǎng)絡(luò)設(shè)計(jì)。
盡早進(jìn)行測(cè)試以了解什么樣的負(fù)載會(huì)產(chǎn)生機(jī)架內(nèi)、 跨機(jī)架、跨數(shù)據(jù)中心的流量。 應(yīng)用程序開(kāi)發(fā)人員必須了解網(wǎng)絡(luò)的設(shè)計(jì),并且要提早與運(yùn)維團(tuán)隊(duì)里的網(wǎng)絡(luò)專(zhuān)家們一起對(duì)它進(jìn)行 review。
分析吞吐率和延遲。
為了理解其影響,必須要對(duì)核心服務(wù)用戶(hù)交互的吞吐量和延遲進(jìn)行分析。 并將這件事與其他一些操作像日常數(shù)據(jù)庫(kù)維護(hù)、 運(yùn)維配置管理(新用戶(hù)添加,用戶(hù)遷移)、 服務(wù)調(diào)試一樣進(jìn)行常規(guī)化。 這將有助于發(fā)現(xiàn)因某些周期性管理任務(wù)引發(fā)的問(wèn)題。 對(duì)于每個(gè)服務(wù)來(lái)說(shuō), 所需的度量值可以與容量規(guī)劃相結(jié)合,比如系統(tǒng)的每秒用戶(hù)請(qǐng)求數(shù)、 系統(tǒng)的并發(fā)在線用戶(hù)數(shù)或者是某些可以將相關(guān)工作負(fù)載映射到資源需求的度量值。
把運(yùn)維工具作為服務(wù)的一部分。
由開(kāi)發(fā)、測(cè)試、 PM、 PE 編寫(xiě)的運(yùn)維工具都要在開(kāi)發(fā)過(guò)程中進(jìn)行代碼 review, checkin 到代碼主干,跟代碼一起進(jìn)行跟蹤維護(hù)和測(cè)試。 常見(jiàn)的情況是, 這些工具非常關(guān)鍵, 但是卻幾乎沒(méi)被測(cè)試過(guò)。
理解訪問(wèn)模式。
規(guī)劃新特性時(shí),一定要考慮它會(huì)給后端存儲(chǔ)帶來(lái)怎樣的負(fù)載。 通常服務(wù)模型和服務(wù)開(kāi)發(fā)者所在的抽象層次已經(jīng)脫離了底層存儲(chǔ),這使得他們無(wú)法注意到負(fù)載會(huì)給底層數(shù)據(jù)庫(kù)帶來(lái)怎樣的影響。 一個(gè)最佳實(shí)踐是給 SPEC (Standard Performance Evaluation Corporation, 系統(tǒng)性能評(píng)估測(cè)試)加上一節(jié): “這個(gè)特性對(duì)系統(tǒng)其它部分有什么影響? ” ,然后在特性上線時(shí)驗(yàn)證負(fù)載的情況是否符合。
將所有東西版本化。
要假設(shè)系統(tǒng)是運(yùn)行在一個(gè)多版本混合的環(huán)境里。目標(biāo)是運(yùn)行單一版本軟件,但在上線和生產(chǎn)測(cè)試時(shí)會(huì)有多版本共存。所有組件的 n和 n+1 版本都要能和平共處。(注:其實(shí)包括配置,腳本和交付相關(guān)都內(nèi)容都需要考慮版本化)
保留上次發(fā)布的 UT 和 FT。
這些測(cè)試是用來(lái)驗(yàn)證 n-1 版本的功能沒(méi)有被破壞掉的重要手段(注:目前更多的實(shí)踐是進(jìn)行自動(dòng)化測(cè)試)。更進(jìn)一步地, 我們強(qiáng)烈推薦要持續(xù)在生產(chǎn)環(huán)境跑驗(yàn)證測(cè)試。
避免單點(diǎn)故障。
單點(diǎn)故障會(huì)導(dǎo)致故障發(fā)生時(shí)服務(wù)或服務(wù)的多個(gè)部分不可用。優(yōu)先采用無(wú)狀態(tài)的實(shí)現(xiàn)。不要把請(qǐng)求或用戶(hù)指定給特定的服務(wù)器。 而是要對(duì)能夠?qū)ω?fù)載進(jìn)行處理的一組服務(wù)器進(jìn)行負(fù)載均衡。 靜態(tài) hash 或者任何的靜態(tài)服務(wù)器任務(wù)分配方式, 隨著時(shí)間的流逝都會(huì)導(dǎo)致數(shù)據(jù)和/或查詢(xún)的傾斜。當(dāng)同一組內(nèi)的機(jī)器都是可互換的時(shí)候,就可以很容易地進(jìn)行水平擴(kuò)展。
自動(dòng)化管理和配置
很多服務(wù)實(shí)現(xiàn)地需要在故障時(shí)向運(yùn)維發(fā)報(bào)警,依賴(lài)人工干預(yù)來(lái)恢復(fù)服務(wù)。這種方式的問(wèn)題首先在于人力成本高,需要 7*24 小時(shí)的運(yùn)維人員成本。 更重要的是,當(dāng)運(yùn)維人員需要頂著巨大壓力做出重要決定時(shí), 大概有 20%的概率會(huì)出現(xiàn)失誤。這種模式既昂貴又容易出錯(cuò), 同時(shí)還降低了整體服務(wù)的可靠性。
但面向自動(dòng)化的設(shè)計(jì)需要給服務(wù)模型強(qiáng)加很多限制。 比如今天的某些大規(guī)模服務(wù)可能會(huì)依賴(lài)于一個(gè)使用了異步復(fù)制進(jìn)行備份的數(shù)據(jù)庫(kù)系統(tǒng)。這樣在主本發(fā)生故障無(wú)法提供服務(wù)而需要切換到副本時(shí),會(huì)因?yàn)閺?fù)制的異步性丟失一些客戶(hù)數(shù)據(jù)。
但是如果不進(jìn)行 failover 切換副本,則會(huì)導(dǎo)致那些數(shù)據(jù)存儲(chǔ)在發(fā)生故障的數(shù)據(jù)庫(kù)服務(wù)器上的用戶(hù)服務(wù)被中斷。很難將是否在這種情況下進(jìn)行 failover 的決定進(jìn)行自動(dòng)化,因?yàn)樗枰藶樽龀雠袛啵?并且需要精確地估算出可能丟失的數(shù)據(jù)量和可能導(dǎo)致的服務(wù)中斷時(shí)長(zhǎng)。 要想實(shí)現(xiàn)自動(dòng)化,就要付出同步復(fù)制的延遲和吞吐率代價(jià)。 如果這樣做了的話,那么 failover 就變成了一個(gè)非常簡(jiǎn)單的決定: 如果主本掛了,那么就將請(qǐng)求路由給副本處理。這種方式更易于自動(dòng)化,并且更不容易出錯(cuò)。
在完成設(shè)計(jì)和部署后再進(jìn)行服務(wù)的自動(dòng)化是很困難的。成功的自動(dòng)化應(yīng)當(dāng)是簡(jiǎn)單和清晰的,易于做出運(yùn)維判斷的。 這反過(guò)來(lái)又取決于細(xì)致的服務(wù)設(shè)計(jì),必要時(shí)可以犧牲一些延遲和吞吐量來(lái)方便自動(dòng)化。通常要在這里面進(jìn)行的權(quán)衡也是很難的,對(duì)于大規(guī)模服務(wù)來(lái)說(shuō), 不同的決策所帶來(lái)的運(yùn)維方面的節(jié)省通常也是數(shù)量級(jí)上的差異。 實(shí)際上我們看到,當(dāng)前最手動(dòng)與最自動(dòng)的服務(wù)在人力開(kāi)銷(xiāo)上的差異多達(dá)兩個(gè)數(shù)量級(jí)。
面向自動(dòng)化設(shè)計(jì)的最佳實(shí)踐如下:
- Be restartable and redundant。 所有操作都應(yīng)是可重做的(restartable),所有持久化狀態(tài)都需要進(jìn)行冗余性存儲(chǔ)。
- 支持地理分布式。 所有的大規(guī)模服務(wù)都應(yīng)當(dāng)支持跨數(shù)據(jù)中心運(yùn)行。 坦率地講,我們這里提到的自動(dòng)化和大多數(shù)的高效率即使是在沒(méi)有地理分布的情況下也是可能的。 但是跨數(shù)據(jù)中心部署能力的缺乏將會(huì)大幅推高運(yùn)維成本。 沒(méi)有地理分布式的支持, 就很難通過(guò)將負(fù)載遷到另一個(gè)數(shù)據(jù)中心來(lái)減輕當(dāng)前數(shù)據(jù)中心的壓力。 地理分布式的缺乏,是一種會(huì)推高成本的運(yùn)維限制。
- 自動(dòng)配置和安裝。配置和安裝,如果是手動(dòng)完成的話,成本高且易發(fā)生問(wèn)題,同時(shí)細(xì)小的配置差異會(huì)慢慢散布到整個(gè)服務(wù), 使得問(wèn)題越來(lái)越難以定位。
-
將配置和代碼作為一體。(注:深有體會(huì),非常贊同) 確保:
1 ) 開(kāi)發(fā)團(tuán)隊(duì)將配置和代碼作為同一個(gè)單元進(jìn)行提供
2 ) 對(duì)于該單元的部署測(cè)試會(huì)以與完全與運(yùn)維人員線上部署方式相一致的形式進(jìn)行
3) 運(yùn)維人員將它們作為同一個(gè)單元進(jìn)行部署
那些將配置和代碼作為同一個(gè)單元, 且對(duì)它們一塊進(jìn)行變更管理的服務(wù)會(huì)更可靠。 -
保證所有的變更都會(huì)有相應(yīng)的審計(jì)記錄。
如果必須要在產(chǎn)品環(huán)境中進(jìn)行某項(xiàng)配置變更, 要保證所有的變更都會(huì)有相應(yīng)的審計(jì)記錄, 以確保清楚地知道進(jìn)行了哪些變更,以及誰(shuí)、 何時(shí)進(jìn)行的,受影響的服務(wù)器有哪些。經(jīng)常掃描所有服務(wù)器以確保它們的狀態(tài)與期望狀態(tài)相一致。 這有助于捕獲安裝和配置故障,盡早檢測(cè)到服務(wù)器配置錯(cuò)誤,發(fā)現(xiàn)未經(jīng)審計(jì)的服務(wù)器配置變化。 -
Manage server roles or personalities rather than servers。
每個(gè) role 或personality 應(yīng)該能支持按需增減服務(wù)器數(shù)。 - 多系統(tǒng)同時(shí)故障會(huì)經(jīng)常發(fā)生。 要意識(shí)到某些故障可能會(huì)同時(shí)影響到很多主機(jī)(電力,交換機(jī),上線)。 不幸的是,具有狀態(tài)的服務(wù),也不可避免的是對(duì)拓?fù)涿舾械摹?關(guān)聯(lián)故障仍會(huì)是現(xiàn)實(shí)存在的。
- 在服務(wù)級(jí)進(jìn)行恢復(fù)。 在服務(wù)級(jí)別上進(jìn)行故障處理和錯(cuò)誤糾正, 保證完整的上下文執(zhí)行環(huán)境可用,而不是更低的軟件層上進(jìn)行。 比如,將冗余構(gòu)建到服務(wù)中,而不是依賴(lài)于在更低的軟件層上進(jìn)行的恢復(fù)。
- 永遠(yuǎn)不要依賴(lài)本機(jī)存儲(chǔ)不可恢復(fù)的信息。 始終堅(jiān)持對(duì)非臨時(shí)的服務(wù)狀態(tài)進(jìn)行備份。
- 保持部署過(guò)程的簡(jiǎn)單。 文件拷貝是理想方案,因?yàn)樗峁┝俗畲蟮牟渴痨`活性。最小化外部依賴(lài)。避免使用復(fù)雜的部署腳本。 應(yīng)當(dāng)避免禁止在同一個(gè)服務(wù)器上運(yùn)行不同組件或相同組件的不同版本的行為。
- Fail services regularly。停掉(take down)數(shù)據(jù)中心,關(guān)掉機(jī)架,讓服務(wù)器斷電。定期引入人為的故障, 不斷暴露出系統(tǒng)、 網(wǎng)絡(luò)和服務(wù)的弱點(diǎn)。 不想在生產(chǎn)環(huán)境下進(jìn)行測(cè)試的服務(wù),也是沒(méi)有信心保證服務(wù)可以經(jīng)歷故障的考驗(yàn)的。 同時(shí)如果沒(méi)有生產(chǎn)測(cè)試,故障恢復(fù)就沒(méi)辦法在需要的時(shí)候工作。
依賴(lài)管理
大規(guī)模服務(wù)中的依賴(lài)管理通常得不到所應(yīng)有的關(guān)注。 一般來(lái)說(shuō),小的組件或服務(wù)的依賴(lài)又不足以證明或顯示依賴(lài)管理所帶來(lái)的復(fù)雜性。 只有在如下情況下,依賴(lài)才會(huì)顯得有意義:
- 依賴(lài)的組件很大或者很復(fù)雜
- 依賴(lài)的服務(wù)的價(jià)值在于它是單一中心實(shí)例
第一種情況的實(shí)例是存儲(chǔ)和一致性算法實(shí)現(xiàn)。第二種情況的實(shí)例是身份和組管理系統(tǒng)。 這些系統(tǒng)的價(jià)值在于,它們是單一的共享實(shí)例,無(wú)法采用多實(shí)例避免這種依賴(lài)。
假設(shè)依賴(lài)關(guān)系滿足上述規(guī)則, 一些管理它們的最佳實(shí)踐如下:
Expect latency。
調(diào)用外部組件可能會(huì)花很長(zhǎng)時(shí)間完成。不要讓一個(gè)組件或服務(wù)的延遲造成完全不相關(guān)的地方的延遲。確保所有的交互有合適的超時(shí),避免長(zhǎng)期占用某項(xiàng)資源。操作冪等性允許超時(shí)后重啟請(qǐng)求,即使請(qǐng)求已經(jīng)部分或完全完成。確保所有的重啟都會(huì)被報(bào)告,同時(shí)限制重啟次數(shù)避免反復(fù)失敗的請(qǐng)求消耗過(guò)多系統(tǒng)資源。
故障隔離。
站點(diǎn)的架構(gòu)必須能夠防止級(jí)聯(lián)失敗??偸恰癴ail fast” 的。依賴(lài)的服務(wù)發(fā)生了故障, 就標(biāo)記為不可用并不再使用它們,以免線程一直等待失敗的組件。
使用經(jīng)驗(yàn)證的穩(wěn)定的組件。
經(jīng)過(guò)驗(yàn)證的技術(shù)總是要好過(guò)那些使用時(shí)像刀口舔血般的新技術(shù)。 穩(wěn)定版的軟件總是要比嘗鮮版更好,無(wú)論新特性看起來(lái)多么誘人。 該規(guī)則也同樣適用于硬件。
實(shí)現(xiàn)內(nèi)部服務(wù)的監(jiān)控和報(bào)警。
如果服務(wù)正在使得它所依賴(lài)的服務(wù)過(guò)載, 被依賴(lài)的服務(wù)需要能夠知道這種情況,并且如果它不能自動(dòng)對(duì)過(guò)載進(jìn)行處理還需要發(fā)送報(bào)警。 如果運(yùn)維人員也無(wú)法快速解決問(wèn)題, 還需要能夠迅速聯(lián)系到來(lái)自?xún)蓚€(gè)團(tuán)隊(duì)的工程師。 所有關(guān)聯(lián)團(tuán)隊(duì)都應(yīng)該保證有工程師可以被隨時(shí)聯(lián)系到。
被依賴(lài)的組件需要有同樣的設(shè)計(jì)出發(fā)點(diǎn)。
被依賴(lài)的服務(wù)以及被依賴(lài)的組件的生產(chǎn)者至少需要跟依賴(lài)者達(dá)成一樣的 SLA。
組件解耦。
在可能的情況下, 確保組件在其他組件發(fā)生故障時(shí)可以繼續(xù)工作,可能是以降級(jí)模式。例如,不是對(duì)每個(gè)連接都重新做認(rèn)證, 而是維護(hù)一個(gè)會(huì)話密鑰,每幾個(gè)小時(shí)更新一下連接狀態(tài)。這樣認(rèn)證服務(wù)器的負(fù)載會(huì)更一致,同時(shí)也保證了在短暫網(wǎng)絡(luò)故障后的重連不會(huì)造成登錄風(fēng)暴。
發(fā)布周期和測(cè)試
在生產(chǎn)環(huán)境下的測(cè)試是必需的,所有的大規(guī)模服務(wù)都應(yīng)該把它作為 QA 方案的一部分。 對(duì)于大多數(shù)服務(wù)來(lái)說(shuō),都至少會(huì)有一個(gè)盡可能接近生產(chǎn)的測(cè)試環(huán)境, 同時(shí)所有優(yōu)秀的工程團(tuán)隊(duì)都會(huì)用實(shí)際的生產(chǎn)負(fù)載來(lái)驅(qū)動(dòng)測(cè)試系統(tǒng)。但我們的經(jīng)驗(yàn)表明,無(wú)論測(cè)試環(huán)境有多好, 總是不可能會(huì)與生產(chǎn)環(huán)境完全一致。 與生產(chǎn)相比, 總是或多或少會(huì)有些差別。 隨著測(cè)試環(huán)境與生產(chǎn)系統(tǒng)的接近, 成本也會(huì)逐步與生產(chǎn)系統(tǒng)相當(dāng)。
我們推薦在新版本服務(wù)經(jīng)過(guò)標(biāo)準(zhǔn)單元測(cè)試、功能測(cè)試和類(lèi)生產(chǎn)環(huán)境測(cè)試后, 就到一個(gè)受限的生產(chǎn)環(huán)境下進(jìn)行最后的測(cè)試。 當(dāng)然,我們都不想進(jìn)入生產(chǎn)環(huán)境的軟件無(wú)法工作,或者是給數(shù)據(jù)一致性帶來(lái)風(fēng)險(xiǎn),因此這一切都務(wù)必要小心翼翼。 嚴(yán)格遵守以下規(guī)則:
- 生產(chǎn)系統(tǒng)要有足夠的冗余,當(dāng)新服務(wù)發(fā)生災(zāi)難性故障時(shí),可以快速恢復(fù)狀態(tài)。
- 絕對(duì)不能破壞數(shù)據(jù)或狀態(tài)一致性(必須先要經(jīng)過(guò)嚴(yán)格的功能測(cè)試)
- 錯(cuò)誤必須能夠被檢測(cè)到,同時(shí)工程團(tuán)隊(duì)(而不是運(yùn)維)必須持續(xù)監(jiān)控受測(cè)代碼的系統(tǒng)狀態(tài)
- 保證所有變更都能被快速回滾,同時(shí)在上線之前回滾步驟也必須經(jīng)過(guò)測(cè)試這看起來(lái)很危險(xiǎn)。 但是我們發(fā)現(xiàn), 使用這種技術(shù)實(shí)際上能夠改善新版本發(fā)布時(shí)的用戶(hù)體驗(yàn)。 部署時(shí)不求快,而是先把一個(gè)數(shù)據(jù)中心的某個(gè)生產(chǎn)系統(tǒng)升級(jí),測(cè)試幾天。然后再把所有數(shù)據(jù)中心的該系統(tǒng)升級(jí)。 (注:灰度發(fā)布的概念)然后再把某個(gè)數(shù)據(jù)中心的所有系統(tǒng)升級(jí)。最后,如果質(zhì)量和性能符合預(yù)期, 再升級(jí)其它數(shù)據(jù)中心。這樣就可以在服務(wù)處于危險(xiǎn)之前發(fā)現(xiàn)問(wèn)題, 同時(shí)也可以切實(shí)地在版本過(guò)渡階段為客戶(hù)提供更好的用戶(hù)體驗(yàn)。 一刀切(Big-bang)的部署方式是非常危險(xiǎn)的。
我們青睞的另一種可能違反直覺(jué)的方式是,在每天正午而不是半夜部署。在晚上部署,出錯(cuò)的風(fēng)險(xiǎn)更高,而且在半夜部署時(shí)如果有異常情況突然發(fā)生,那么能處理這些問(wèn)題的工程師肯定會(huì)少些。這樣做的目標(biāo)是為了最小化開(kāi)發(fā)和運(yùn)維人員與系統(tǒng)的總體交互次數(shù),尤其在正常工作日之外的, 降低成本的同時(shí),質(zhì)量也得到提高。
一些發(fā)布周期和測(cè)試方面的最佳實(shí)踐:
經(jīng)常進(jìn)行發(fā)布。
直覺(jué)上看,人們可能會(huì)認(rèn)為發(fā)布越頻繁會(huì)越困難,同時(shí)也越容易出錯(cuò)。 但是,我們卻發(fā)現(xiàn)發(fā)布越頻繁大爆炸(big-bang)式的變更會(huì)越少。
這樣發(fā)布的質(zhì)量?jī)A向于更高, 客戶(hù)的體驗(yàn)也會(huì)更好。 一次良好發(fā)布的酸性測(cè)試(acid test),應(yīng)該是用戶(hù)體驗(yàn)可能發(fā)生變化,但是圍繞著可用性和延遲的運(yùn)維性問(wèn)題數(shù)在整個(gè)發(fā)布周期內(nèi)應(yīng)該保持不變。 我們比較喜歡以三個(gè)月為一個(gè)發(fā)布周期, 但是也可以視具體情況作出調(diào)整。 我們感覺(jué),正常來(lái)說(shuō)都應(yīng)該是不多于 3 個(gè)月, 而且有些服務(wù)已經(jīng)是在以周為單位進(jìn)行發(fā)布了(注:敏捷交付模式)。 如果周期超過(guò) 3 個(gè)月, 通常都是很危險(xiǎn)的。
利用線上數(shù)據(jù)發(fā)現(xiàn)問(wèn)題。
大規(guī)模系統(tǒng)中的質(zhì)量保證,是個(gè)數(shù)據(jù)挖掘和可視化問(wèn)題,而不是測(cè)試問(wèn)題。 每個(gè)人都應(yīng)該專(zhuān)注于如何從生產(chǎn)環(huán)境中的大量數(shù)據(jù)中獲取到最有價(jià)值的信息。 可以采用如下一些策略:
- 可衡量的發(fā)布標(biāo)準(zhǔn)。 定義出關(guān)于所期望的用戶(hù)體驗(yàn)的具體標(biāo)準(zhǔn)并持續(xù)監(jiān)測(cè)它。 如果可用性目標(biāo)設(shè)定為 99%, 那么就對(duì)可用性進(jìn)行測(cè)量看它是否達(dá)標(biāo)。 如果無(wú)法達(dá)標(biāo),要進(jìn)行報(bào)警和診斷。
- 始終對(duì)實(shí)際數(shù)字進(jìn)行收集。 收集實(shí)際的度量值, 而不是那些紅紅綠綠的圖或其他形式的摘要報(bào)告。 摘要和圖表有用,但是對(duì)于問(wèn)題診斷來(lái)說(shuō)還是需要原始數(shù)據(jù)。
- 最小化“false positives(誤報(bào))”。 在數(shù)據(jù)不正確時(shí),人們很快就會(huì)放棄對(duì)它的關(guān)注。不過(guò)度報(bào)警很重要,否則運(yùn)維人員很快就會(huì)習(xí)慣于忽略它們。這非常重要, 以至于即使是附帶地把某些真實(shí)問(wèn)題隱藏掉也是可以接受的。
- 分析趨勢(shì)。 這個(gè)可以用來(lái)預(yù)測(cè)問(wèn)題。 例如,當(dāng)系統(tǒng)中的數(shù)據(jù)流動(dòng)速率異于往常時(shí), 通常預(yù)示著更大的問(wèn)題。 仔細(xì)挖掘現(xiàn)有的可用數(shù)據(jù)。
- 使系統(tǒng)健康程度保持高度可見(jiàn)。 需要為整個(gè)組織提供一個(gè)隨處可查并實(shí)時(shí)顯示的系統(tǒng)健康狀況報(bào)告。 構(gòu)建一個(gè)內(nèi)部網(wǎng)站,使得大家可以隨時(shí)查看當(dāng)前系統(tǒng)狀態(tài)。
- 持續(xù)監(jiān)控。 值得一提的是, 人們必須要每天查看這些監(jiān)控?cái)?shù)據(jù)。 每個(gè)人都應(yīng)該這樣做, 但是也要為這項(xiàng)工作明確地指定某些負(fù)責(zé)人。
加大工程投入。
良好的工程化可以最小化運(yùn)維需求, 同時(shí)可以將問(wèn)題消除在萌芽狀態(tài)。 一個(gè)常見(jiàn)的一個(gè)現(xiàn)象是, 組織通過(guò)不斷地?cái)U(kuò)大運(yùn)維團(tuán)隊(duì)來(lái)解決規(guī)模問(wèn)題,而不是花時(shí)間設(shè)計(jì)實(shí)現(xiàn)一個(gè)可伸縮的、 可靠的系統(tǒng)。 那些起初沒(méi)有考慮過(guò)大規(guī)模問(wèn)題的服務(wù), 往往后面都會(huì)變得手忙腳亂。
支持版本回滾。
版本回滾支持應(yīng)是強(qiáng)制性的, 同時(shí)在上線之前必須經(jīng)過(guò)測(cè)試和證明。 如果沒(méi)有回滾支持,任何形式的生產(chǎn)級(jí)測(cè)試都將是非常危險(xiǎn)的。 回滾到前一版本就像降落傘上的“開(kāi)傘索”, 應(yīng)保證它在任意部署中都是可用的。
保持向前和向后兼容性。
Forwards Compatibility, 向前兼容。 Forward 有“將來(lái)” 的含義, 因此是指以前的版本支持現(xiàn)在版本生成的數(shù)據(jù),現(xiàn)在的版本支持以后的版本數(shù)據(jù)。 Backwards Compatibility,向后兼容。 Backward 有“回頭”的意思, 所以是指現(xiàn)在的版本可以支持以前的版本數(shù)據(jù)}。 這一點(diǎn)與前面一點(diǎn)非常相關(guān)。 對(duì)文件格式、 接口、 日志/調(diào)試信息、 儀表、 監(jiān)控和組件間的連接點(diǎn)進(jìn)行的改變, 都是潛在的風(fēng)險(xiǎn)。 不要丟掉對(duì)舊文件格式的支持,否則未來(lái)將沒(méi)有機(jī)會(huì)回滾到老版本。
單機(jī)部署支持。
這既是測(cè)試的需求也是開(kāi)發(fā)的需求。 整個(gè)服務(wù)必須可以很容易地托管到單一系統(tǒng)中。 對(duì)于某些單服務(wù)器無(wú)法實(shí)現(xiàn)的組件(比如,它依賴(lài)于一個(gè)外部的、不支持單機(jī)部署的服務(wù)),需要為它編寫(xiě)模擬器以支持單機(jī)部署。
如果不支持這點(diǎn),那么單元測(cè)試將很難進(jìn)行,同時(shí)也沒(méi)法完全展開(kāi)。 同時(shí),如果運(yùn)行整個(gè)系統(tǒng)很困難,開(kāi)發(fā)人員也會(huì)傾向于在組件的級(jí)別上進(jìn)行開(kāi)發(fā),而不是系統(tǒng)級(jí)。
針對(duì)負(fù)載進(jìn)行壓力測(cè)試。
采用兩倍(或更多)的負(fù)載來(lái)運(yùn)行生產(chǎn)系統(tǒng)的某些子集, 確保系統(tǒng)在高于預(yù)期負(fù)載情況下的行為仍然是可理解的, 以及不會(huì)隨著負(fù)載的上升而宕掉。
在新發(fā)布之前進(jìn)行容量和性能測(cè)試。
除了要在服務(wù)級(jí)上進(jìn)行,還要對(duì)每個(gè)組件進(jìn)行, 因?yàn)樨?fù)載特征會(huì)隨著時(shí)間發(fā)生變化。 需要盡早捕獲系統(tǒng)內(nèi)部的問(wèn)題及退化現(xiàn)象。
增量/迭代地進(jìn)行構(gòu)建和部署。
在開(kāi)發(fā)的早期階段, 先把整個(gè)服務(wù)的骨架先搭建好。 這個(gè)完整的服務(wù)可能幾乎做不了什么, 但是它可以讓測(cè)試和開(kāi)發(fā)人員更具有產(chǎn)品思維, 可以一開(kāi)始就站在用戶(hù)的角度思考問(wèn)題。 在構(gòu)建軟件系統(tǒng)時(shí)這是一個(gè)非常好的實(shí)踐, 但對(duì)于服務(wù)來(lái)說(shuō)更尤為重要。
采用真實(shí)數(shù)據(jù)進(jìn)行測(cè)試。
將生產(chǎn)環(huán)境中的用戶(hù)請(qǐng)求和工作負(fù)載搬到測(cè)試環(huán)境中。 挑選一些生產(chǎn)數(shù)據(jù),并將它們放到測(cè)試環(huán)境中。 多樣化的真實(shí)用戶(hù)群體在 bug 的發(fā)現(xiàn)上總是更有創(chuàng)造力。 顯然, 必須要進(jìn)行隱私承諾,非常關(guān)鍵的是保證數(shù)據(jù)永遠(yuǎn)不會(huì)泄露回到生產(chǎn)系統(tǒng)中。
運(yùn)行系統(tǒng)級(jí)驗(yàn)收測(cè)試。
在本地運(yùn)行一些可以加速迭代開(kāi)發(fā)過(guò)程的完整性檢查。為避免產(chǎn)生繁重的維護(hù)成本,它們都應(yīng)當(dāng)是系統(tǒng)級(jí)的。
在完整環(huán)境中進(jìn)行測(cè)試開(kāi)發(fā)。
留出一定的硬件,以可以進(jìn)行特定規(guī)模的測(cè)試。最重要的是, 在這些環(huán)境中使用那些與生產(chǎn)系統(tǒng)相同的數(shù)據(jù)集合和挖掘技術(shù),以最大化資源投入的價(jià)值。
硬件選型和標(biāo)準(zhǔn)化
略
運(yùn)維和容量規(guī)劃
要高效地運(yùn)維服務(wù),關(guān)鍵在于構(gòu)建系統(tǒng)時(shí)消除各種需要運(yùn)維交互的過(guò)程。 目標(biāo)在于讓一個(gè)高可靠的、 724 小時(shí)可用的服務(wù)只需要 58 小時(shí)工作的運(yùn)維團(tuán)隊(duì)維護(hù)即可。
但是,可能會(huì)發(fā)生不尋常的故障,而且系統(tǒng)或多個(gè)系統(tǒng)可能會(huì)無(wú)法恢復(fù)正常在線。要理解這種可能性的發(fā)生,并將受損系統(tǒng)的下線過(guò)程自動(dòng)化。 依賴(lài)于運(yùn)維人員手動(dòng)更新 SQL 表或者是使用特別的技術(shù)移動(dòng)數(shù)據(jù),都可能會(huì)招致災(zāi)難。 處理故障的過(guò)程中也容易產(chǎn)生失誤。 運(yùn)維團(tuán)隊(duì)需要預(yù)料遇到各種故障時(shí)的正確應(yīng)對(duì)方式,并將這些過(guò)程提前進(jìn)行編寫(xiě)和測(cè)試。 一般來(lái)說(shuō), 開(kāi)發(fā)團(tuán)隊(duì)要將緊急恢復(fù)操作自動(dòng)化,并必須要對(duì)它們進(jìn)行測(cè)試。 很明顯,無(wú)法將所有的故障都提前預(yù)料到, 但是通常通過(guò)一小組恢復(fù)動(dòng)作的集合就可以從類(lèi)型廣泛的故障中恢復(fù)過(guò)來(lái)。本質(zhì)上來(lái)說(shuō),是需要構(gòu)建和測(cè)試可以根據(jù)故障范圍和危害以不同方式使用及組合的“恢復(fù)內(nèi)核”。
恢復(fù)腳本需要在生產(chǎn)環(huán)境下測(cè)試。 沒(méi)有經(jīng)過(guò)頻繁測(cè)試的東西是無(wú)法工作的, 因此不要實(shí)現(xiàn)團(tuán)隊(duì)沒(méi)有勇氣去使用的任何東西。 如果在生產(chǎn)環(huán)境下測(cè)試的風(fēng)險(xiǎn)太高,那么說(shuō)明腳本要么是沒(méi)準(zhǔn)備好,要么是在緊急情況下使用時(shí)也不會(huì)安全。 這里的關(guān)鍵點(diǎn)是, 災(zāi)難總是在發(fā)生,同時(shí)那些因?yàn)榛謴?fù)步驟未按預(yù)期執(zhí)行而導(dǎo)致由小災(zāi)難演變?yōu)榇鬄?zāi)難的情況也是屢見(jiàn)不鮮。 要預(yù)料到這些情況, 并且要能在不造成更
多的數(shù)據(jù)丟失和不服務(wù)時(shí)間的前提下, 將服務(wù)恢復(fù)過(guò)程自動(dòng)化。
增強(qiáng)開(kāi)發(fā)團(tuán)隊(duì)責(zé)任感。
在這方面, Amazon 應(yīng)該算是最激進(jìn)的了,他們的格言是“you built it, you manage it(注:跟Eat Your Own Dog Food有類(lèi)似意思)”。 他們的主張要比我們現(xiàn)在所采用的方式稍微強(qiáng)些,但是這無(wú)疑是一個(gè)正確的方向。 如果開(kāi)發(fā)總是被在午夜吵醒,那么自動(dòng)化就會(huì)是必然結(jié)果。 但是如果是運(yùn)維被吵醒,通常的反應(yīng)是擴(kuò)充運(yùn)維團(tuán)隊(duì)。
只進(jìn)行軟刪除。
絕不要?jiǎng)h除任何東西,只是將它們標(biāo)記為已刪除。 當(dāng)有新數(shù)據(jù)進(jìn)來(lái)時(shí), 將請(qǐng)求記錄下來(lái)。 保存一個(gè)以?xún)芍?或更長(zhǎng)時(shí)間)為單位滾動(dòng)的變更歷史記錄, 以便從軟件或操作錯(cuò)誤中恢復(fù)。 比如有誰(shuí)犯了錯(cuò),忘記在 delete語(yǔ)句中加上 where 子句(以前曾經(jīng)發(fā)生過(guò)并且也難保將來(lái)不會(huì)再發(fā)生), 數(shù)據(jù)的所有邏輯拷貝都會(huì)被刪除。 RAID 和鏡像都無(wú)法防止這種形式的錯(cuò)誤。 數(shù)據(jù)恢復(fù)能力可以讓一個(gè)原本非常嚴(yán)重的問(wèn)題變成一個(gè)微小的,不起眼的問(wèn)題。對(duì)于那些已經(jīng)進(jìn)行了離線備份的系統(tǒng)來(lái)說(shuō), 只需要額外記錄那些上次備份之后進(jìn)來(lái)的數(shù)據(jù)即可。但是, 謹(jǐn)慎起見(jiàn),多備份一些會(huì)更保險(xiǎn)。
跟蹤資源分配。
理解容量規(guī)劃中的額外負(fù)載帶來(lái)的成本開(kāi)銷(xiāo)。 每個(gè)服務(wù)都應(yīng)該開(kāi)發(fā)一些像并發(fā)在線用戶(hù)、 每秒請(qǐng)求數(shù)或者其他的一些相關(guān)指標(biāo)。 無(wú)論是何種指標(biāo), 都需要在負(fù)載的此種測(cè)量方法和所需的資源之間有一個(gè)直接的已知關(guān)系。 所估計(jì)的負(fù)載數(shù)應(yīng)通過(guò)銷(xiāo)售和市場(chǎng)團(tuán)隊(duì)的反饋得到, 同時(shí)將會(huì)被運(yùn)維團(tuán)隊(duì)用來(lái)進(jìn)行容量規(guī)劃。 不同的服務(wù)具有不同的變化速度, 同時(shí)有不同的訂購(gòu)周期要求。 對(duì)于我們的服務(wù)來(lái)說(shuō),每 90 天會(huì)更新一下市場(chǎng)預(yù)測(cè), 每 30天更新一次容量規(guī)劃和訂購(gòu)需求。
一次只進(jìn)行一個(gè)變更。
碰到問(wèn)題時(shí), 應(yīng)該一次只對(duì)環(huán)境做一個(gè)變更。 這看起來(lái)顯而易見(jiàn),但是我們也多次看到過(guò)因多個(gè)變更導(dǎo)致的因果關(guān)系無(wú)法確定的情況發(fā)生。
使所有東西可配置。
任何可能在產(chǎn)品系統(tǒng)中發(fā)生改變的東西都應(yīng)該是在生產(chǎn)環(huán)境下可配置和調(diào)整的,而不需要改變代碼。 即使某個(gè)值看起來(lái)沒(méi)有很好的在生產(chǎn)環(huán)境中發(fā)生變更的理由,如果很容易的話也應(yīng)讓它可配置。 但是不要在生產(chǎn)環(huán)境中隨意更改它們, 同時(shí)應(yīng)該對(duì)系統(tǒng)連同那些將在生產(chǎn)系統(tǒng)中使用的配置一塊進(jìn)行嚴(yán)格的測(cè)試。 但是當(dāng)生產(chǎn)出現(xiàn)問(wèn)題時(shí), 與編碼、 編譯、 測(cè)試、部署相比,簡(jiǎn)單地修改下配置總是要更簡(jiǎn)單、 安全、 快速。
審計(jì)、 監(jiān)控和報(bào)警
運(yùn)維人員無(wú)法在部署中再對(duì)服務(wù)進(jìn)行調(diào)整(instrument)。在開(kāi)發(fā)過(guò)程中要付出足夠的努力, 來(lái)確保系統(tǒng)中的所有組件都可以產(chǎn)生相應(yīng)的性能數(shù)據(jù)、 健康數(shù)據(jù)以及吞吐率等數(shù)據(jù)。在任何有配置變更發(fā)生的時(shí)候,都要在審計(jì)日志中記錄下改了什么,誰(shuí)改的,什么時(shí)間改的。 在生產(chǎn)環(huán)境出現(xiàn)異常時(shí),第一個(gè)要回答的問(wèn)題就是最近到底進(jìn)行過(guò)哪些變更。 如果沒(méi)有審計(jì)跟蹤,那么答案通常是“沒(méi)有改過(guò)什么”, 而通常最可能的情況就是正是因?yàn)槟硞€(gè)變更導(dǎo)致了問(wèn)題。
報(bào)警是一門(mén)藝術(shù)。 有一種傾向就是對(duì)所有事件進(jìn)行報(bào)警,開(kāi)發(fā)者期望可以從中發(fā)現(xiàn)有趣的事情, 這就導(dǎo)致很多服務(wù)的第一版通常都會(huì)產(chǎn)生大量根本沒(méi)人會(huì)看的無(wú)用報(bào)警信息。 要提高效率,每個(gè)報(bào)警都應(yīng)該對(duì)應(yīng)著一個(gè)問(wèn)題。 否則,運(yùn)維團(tuán)隊(duì)將會(huì)習(xí)慣于將它們忽略。 我們不知道除了交互式地對(duì)報(bào)警條件進(jìn)行調(diào)整外, 還有何靈丹妙藥可以讓每個(gè)報(bào)警都正確, 以保證所有關(guān)鍵事件都會(huì)被報(bào)警, 在不需要采取任何措施的情況下就不報(bào)警。 要得到正確的報(bào)警級(jí)別,有兩個(gè)指標(biāo)可能會(huì)有幫助, 并值得進(jìn)行追蹤:
1)報(bào)警和實(shí)際故障比 (理想情況它的值應(yīng)接近1)
2)沒(méi)有產(chǎn)生相應(yīng)報(bào)警的系統(tǒng)故障數(shù) (理想情況它的值應(yīng)接近 0)。
Instrument everything。
對(duì)通過(guò)系統(tǒng)的每個(gè)客戶(hù)交互和事務(wù)進(jìn)行監(jiān)測(cè), 并報(bào)告異常。 這是一個(gè) “Runners” (可以合成工作負(fù)載來(lái)模擬生產(chǎn)環(huán)境中的用戶(hù)交互)可以施展的地方,但是僅有它們還不夠。 如果只使用 Runners,我們?cè)吹揭粋€(gè)嚴(yán)重問(wèn)題甚至需要幾天時(shí)間才被發(fā)現(xiàn),因?yàn)闃?biāo)準(zhǔn)工作負(fù)載一直被處理得很好, 然后還要再花幾天時(shí)間才能查到原因。
數(shù)據(jù)是最有價(jià)值的資產(chǎn)。
如果對(duì)系統(tǒng)正常行為沒(méi)有很好的理解,那么在它發(fā)生異常時(shí)也沒(méi)法很好地進(jìn)行處理。 需要對(duì)關(guān)于系統(tǒng)行為的大量數(shù)據(jù)進(jìn)行收集以確定系統(tǒng)狀態(tài)是否正常。 很多服務(wù)都經(jīng)歷過(guò)災(zāi)難性的故障,但是只有在電話鈴響起時(shí),人們才意識(shí)到故障的發(fā)生。
具有服務(wù)的客戶(hù)視角。
進(jìn)行 E2E 測(cè)試。 僅有 Runners 雖不足夠,但是它們可以用來(lái)確保服務(wù)在完整運(yùn)行。確保復(fù)雜和重要的路徑能夠被 Runners 測(cè)試到。避免誤報(bào),如果 Runners 的失敗可以被忽略,那么就修改測(cè)試使得它是不可忽略的。 再次強(qiáng)調(diào)一下,一旦人們習(xí)慣了忽略數(shù)據(jù),以后即使再真的發(fā)生也無(wú)法再得到及時(shí)的關(guān)注。
對(duì)生產(chǎn)環(huán)境測(cè)試進(jìn)行監(jiān)測(cè)。
要想安全地在生產(chǎn)環(huán)境中進(jìn)行測(cè)試, 需進(jìn)行完整的測(cè)試和監(jiān)控。 如果組件發(fā)生了故障,需要能夠快速地監(jiān)測(cè)到。
延遲是最棘手的問(wèn)題。
比如像 IO 緩慢, 雖未成故障但是處理變慢這樣的問(wèn)題。 這些都很難發(fā)現(xiàn),需仔細(xì)進(jìn)行監(jiān)測(cè)才能發(fā)現(xiàn)。
要有足夠的生產(chǎn)數(shù)據(jù)。
為了找到問(wèn)題,數(shù)據(jù)必須是可用的。 及早構(gòu)建細(xì)粒度的監(jiān)控, 否則后面進(jìn)行改造的成本會(huì)很高。 我們所依賴(lài)的重要數(shù)據(jù)包括:
為所用操作采用性能計(jì)數(shù)器。 至少要將操作延遲及每秒的操作數(shù)記錄下來(lái)。 這些數(shù)據(jù)的起伏通常是一個(gè)危險(xiǎn)信號(hào)。
對(duì)所有數(shù)據(jù)進(jìn)行審計(jì)跟蹤。 每當(dāng)某人做了某事,尤其是重要之事,都要進(jìn)行記錄。 這樣做主要有兩個(gè)目的:首先, 日志可以用來(lái)進(jìn)行挖掘以找出用戶(hù)經(jīng)常進(jìn)行哪些操作(在我們的例子中,就是他們經(jīng)常進(jìn)行何種查詢(xún));其次, 可以用它來(lái)在發(fā)現(xiàn)問(wèn)題時(shí)幫助進(jìn)行 debug。
與此相關(guān)的一個(gè)觀點(diǎn):如果所有人都使用同一個(gè)賬號(hào)來(lái)管理系統(tǒng), 這樣做不會(huì)帶來(lái)太多好處。 一個(gè)非常糟糕的想法, 但是并不罕見(jiàn)。跟蹤所有容錯(cuò)機(jī)制。 容錯(cuò)機(jī)制會(huì)將故障隱藏。 每當(dāng)重試發(fā)生,或?qū)?shù)據(jù)從一個(gè)地方拷貝到另一個(gè)地方, 或機(jī)器重啟以及服務(wù)重啟時(shí),都進(jìn)行跟蹤。 在容錯(cuò)機(jī)制隱藏了小故障時(shí),要能了解到并對(duì)它進(jìn)行追蹤,防止小故障演變成大故障。我們?cè)?jīng)有一個(gè) 2000 臺(tái)機(jī)器的服務(wù)在幾天內(nèi)慢慢地下降到只有 400 臺(tái)可用, 但是一開(kāi)始卻沒(méi)人注意到。
跟蹤針對(duì)重要實(shí)體的所有操作。 為發(fā)生在每個(gè)重要實(shí)體上的事件記錄一個(gè)“審計(jì)日志”, 無(wú)論實(shí)體是一個(gè)文檔還是多個(gè)文檔組成的集合。 在運(yùn)行數(shù)據(jù)分析時(shí),通常能夠通過(guò)數(shù)據(jù)發(fā)現(xiàn)異常。 要了解數(shù)據(jù)的來(lái)源及其所經(jīng)過(guò)的處理過(guò)程。 到了項(xiàng)目后期再添加這些功能會(huì)變得特別困難。
斷言。 自由地在整個(gè)產(chǎn)品中使用斷言。 收集產(chǎn)生的日志以及程序奔潰后的Core文件,并對(duì)它們進(jìn)行研究。 對(duì)于那些在同一個(gè)進(jìn)程邊界內(nèi)運(yùn)行了多個(gè)服務(wù),以及無(wú)法使用斷言的地方, 要寫(xiě)下追蹤記錄。
保留歷史數(shù)據(jù)。 歷史上的性能和日志數(shù)據(jù)對(duì)于趨勢(shì)分析和問(wèn)題診斷來(lái)說(shuō)都是非常必要的。
日志可配置。
支持可配置的日志, 日志可以根據(jù)調(diào)試需求選擇性地打開(kāi)、 關(guān)閉(注:應(yīng)該還具備熱開(kāi)關(guān)和自動(dòng)降級(jí)功能)。 在故障期間去部署具有額外監(jiān)控的新構(gòu)建版本是非常危險(xiǎn)的。
向監(jiān)控系統(tǒng)暴露健康信息。
考慮多種從外部對(duì)系統(tǒng)健康狀況進(jìn)行監(jiān)控的方法,并使之易于在生產(chǎn)環(huán)境下進(jìn)行監(jiān)控。
保證所有被報(bào)告的錯(cuò)誤都有與之相應(yīng)的處理動(dòng)作。
問(wèn)題會(huì)發(fā)生。事情會(huì)出錯(cuò)。如果代碼中的一個(gè)不可恢復(fù)的錯(cuò)誤被檢測(cè)到并記入日志, 或者是報(bào)告為錯(cuò)誤,錯(cuò)誤信息應(yīng)該能揭示錯(cuò)誤產(chǎn)生的可能原因及建議的處理方法。 不具備可操作性的錯(cuò)誤報(bào)告是無(wú)用的,并且時(shí)間長(zhǎng)了它們會(huì)被忽略,而真正的故障將會(huì)被錯(cuò)過(guò)。
實(shí)現(xiàn)生產(chǎn)問(wèn)題的快速診斷。
- 為診斷提供足夠信息。 當(dāng)問(wèn)題被標(biāo)記出來(lái)時(shí),提供足以讓人進(jìn)行診斷的信息。 否則, 進(jìn)入門(mén)檻將會(huì)過(guò)高,同時(shí)標(biāo)記也會(huì)被忽略。 比如不要僅僅是說(shuō)“有 10 個(gè)查詢(xún)沒(méi)有返回結(jié)果”, 還需再加上“下面是它們的列表及問(wèn)題出現(xiàn)次數(shù)”。
- 證據(jù)鏈。 確保有一個(gè)可以讓開(kāi)發(fā)人員進(jìn)行問(wèn)題診斷的從頭到尾的完整路徑。 這通常是通過(guò)日志實(shí)現(xiàn)的。
- 在生產(chǎn)環(huán)境中進(jìn)行 debug。 我們更喜歡這樣一種模式,在該模式中, 系統(tǒng)幾乎從不會(huì)被包括運(yùn)維在內(nèi)的任何人直接觸碰, 而 debug 是通過(guò)讓系統(tǒng)產(chǎn)生快照, 將內(nèi)存內(nèi)容 dump 出來(lái),然后轉(zhuǎn)移出生產(chǎn)環(huán)境再進(jìn)行的。當(dāng)在生產(chǎn)環(huán)境中進(jìn)行 debug 是唯一選擇時(shí),開(kāi)發(fā)者則是不二人選。 確保他們對(duì)于可以在生產(chǎn)環(huán)境中做哪些事情是經(jīng)過(guò)嚴(yán)格培訓(xùn)的。 我們的經(jīng)驗(yàn)表明, 系統(tǒng)在生產(chǎn)環(huán)境中被觸碰地越少, 客戶(hù)滿意度越高。 因此我們建議, 一定要竭盡全力避免對(duì)生產(chǎn)環(huán)境中的系統(tǒng)進(jìn)行改動(dòng)。
- 記錄所有的重要?jiǎng)幼鳌?/strong> 每當(dāng)系統(tǒng)執(zhí)行重要?jiǎng)幼鲿r(shí), 尤其是在收到網(wǎng)絡(luò)請(qǐng)求或修改數(shù)據(jù)時(shí), 要記錄下發(fā)生的事情。 包括用戶(hù)何時(shí)發(fā)送了命令以及系統(tǒng)內(nèi)部做了什么。 有了這些記錄, 對(duì)問(wèn)題調(diào)查大有裨益。 更重要的是,還可以開(kāi)發(fā)出挖掘工具來(lái)找到有用的聚合結(jié)果, 比如當(dāng)前的用戶(hù)正在執(zhí)行哪些種類(lèi)的查詢(xún)(比如, 哪些關(guān)鍵字,多少關(guān)鍵字等等)。
優(yōu)雅降級(jí)和準(zhǔn)入控制
有些時(shí)候比如受到 DOS 攻擊或使用模式發(fā)生某些改變時(shí),會(huì)導(dǎo)致負(fù)載突然爆發(fā)。服務(wù)需要能夠進(jìn)行優(yōu)雅降級(jí)及準(zhǔn)入控制。 比如在 9.11 期間, 大多數(shù)新聞服務(wù)都崩潰了, 無(wú)法為任何用戶(hù)提供可用的服務(wù)。 與此相比, 就算是僅能夠提供所有文章的一部分子集也是一個(gè)更好的選擇。 兩個(gè)最佳實(shí)踐,“big red switch” 和準(zhǔn)入控制, 需要針對(duì)每個(gè)服務(wù)進(jìn)行量身定制。 但是這兩個(gè)都是非常強(qiáng)大和必要的。
支持“big red switch”。
“big red switch”的想法最初源自于 Windows Live Search團(tuán)隊(duì),它非常強(qiáng)大。 我們對(duì)它進(jìn)行了一些擴(kuò)展, 使得它可以應(yīng)用在那些與搜索具有顯著不同的事務(wù)型服務(wù)中(注:降級(jí)概念)。 這個(gè)想法非常強(qiáng)大,實(shí)際上可以應(yīng)用到任何地方。 大體來(lái)說(shuō),“big red switch” 是一種當(dāng)服務(wù)不再滿足它的 SLA 或迫在眉睫時(shí), 可采取的經(jīng)過(guò)設(shè)計(jì)和測(cè)試的動(dòng)作。將優(yōu)雅降級(jí)比喻為“big red switch”,稍微有些不太恰當(dāng),但核心的意思是指那種可以在緊急情況下摒棄那些非關(guān)鍵負(fù)載的能力。
“big red switch” 概念是以丟棄或延遲非關(guān)鍵負(fù)載為代價(jià), 保證關(guān)鍵處理過(guò)程能繼續(xù)進(jìn)行的關(guān)鍵。 根據(jù)設(shè)計(jì),這種情況應(yīng)永不發(fā)生,但是當(dāng)真的發(fā)生時(shí)這也不失為一個(gè)好方法。 等到服務(wù)已處于危險(xiǎn)的情況下,再考慮這些就太遲了。 如果有些負(fù)載可以被暫時(shí)放入隊(duì)列后面再處理, 那這也可以作為“big redswitch” 的候選。 另外如果在關(guān)閉高級(jí)查詢(xún)的情況下,事務(wù)可以繼續(xù)執(zhí)行,那這也可以作為一個(gè)候選。 關(guān)鍵在于確定碰到問(wèn)題時(shí)系統(tǒng)所需的最小集合,然后實(shí)現(xiàn)關(guān)閉那些不必要的服務(wù)的開(kāi)關(guān),并進(jìn)行測(cè)試。 需要注意的是,正確的“big red switch” 應(yīng)是可逆的。 同時(shí)應(yīng)對(duì)開(kāi)關(guān)的重置進(jìn)行測(cè)試, 確保所有服務(wù)可以回到完整服務(wù)狀態(tài), 包括所有的批處理任務(wù)及先前被暫停的非關(guān)鍵工作。
準(zhǔn)入控制。
第二個(gè)重要概念是準(zhǔn)入控制(注:限流概念)。 如果當(dāng)前的負(fù)載系統(tǒng)已經(jīng)無(wú)法處理了,那么再往系統(tǒng)中增加負(fù)載也只是會(huì)讓更多的用戶(hù)產(chǎn)生糟糕的體驗(yàn)。 如何實(shí)現(xiàn)這一點(diǎn)與系統(tǒng)本身有關(guān), 某些系統(tǒng)比其他系統(tǒng)更容易完成。 以電子郵件處理服務(wù)為例,如果系統(tǒng)已經(jīng)超負(fù)荷, 并開(kāi)始排隊(duì),此時(shí)最好不要再接收郵件而是讓它們?cè)趤?lái)源隊(duì)列中等候。 這樣可以產(chǎn)生效果并能實(shí)際減少總體服務(wù)延遲的關(guān)鍵原因是, 如果隊(duì)列形成處理時(shí)間會(huì)變更慢。 如果我們不允許隊(duì)列的建立,那么吞吐量將會(huì)更高。 另一種技術(shù)是: 提供服務(wù)時(shí)高端用戶(hù)優(yōu)先于非高端用戶(hù), 注冊(cè)用戶(hù)優(yōu)先于訪客, 或者是訪客優(yōu)于用戶(hù)如果是以“試用和購(gòu)買(mǎi)”為商業(yè)模式的話。
準(zhǔn)入計(jì)量。
另一個(gè)非常重要概念是上面所確定的準(zhǔn)入控制點(diǎn)的修改。 如果系統(tǒng)發(fā)生故障并宕機(jī), 為確保一切正?;謴?fù)時(shí)必須能夠緩緩進(jìn)行。 比如先讓一個(gè)用戶(hù)進(jìn)入, 然后每秒允許 10 個(gè)用戶(hù)進(jìn)入, 如此慢慢加大。 對(duì)于每個(gè)服務(wù)來(lái)說(shuō),擁有一個(gè)細(xì)粒度的旋鈕可以在重新上線或從災(zāi)難性失敗中恢復(fù)時(shí)緩慢增加使用量,是至關(guān)重要的。 在任何服務(wù)的第一個(gè)版本中很少會(huì)包含這種能力。 對(duì)于一個(gè)有客戶(hù)的服務(wù)來(lái)說(shuō),一定有方法來(lái)通知它的客戶(hù)暫時(shí)無(wú)法提供服務(wù)以及何時(shí)會(huì)恢復(fù)。 這就允許客戶(hù)端在可以接受的情況下繼續(xù)修改本地?cái)?shù)據(jù), 同時(shí)也可以讓客戶(hù)端暫時(shí)退下避免干擾服務(wù), 讓服務(wù)可以盡快恢復(fù)上線。
這樣也同時(shí)為服務(wù) owner 提供了一個(gè)直接與用戶(hù)溝通的機(jī)會(huì), 并可借此調(diào)整他們的期望。 另外的一個(gè)可以避免所有客戶(hù)端同時(shí)涌向服務(wù)端的技巧是:故意制造抖動(dòng)和對(duì)每個(gè)實(shí)體進(jìn)行自動(dòng)備份。
客戶(hù)和媒體溝通計(jì)劃
系統(tǒng)發(fā)生故障時(shí), 需要就由此引發(fā)的延遲和其他問(wèn)題與客戶(hù)進(jìn)行主動(dòng)溝通。 將系統(tǒng)狀態(tài)告知用戶(hù),并說(shuō)明預(yù)計(jì)在何時(shí)會(huì)完全可用。如果用戶(hù)能夠了解什么正在發(fā)生,并且對(duì)于服務(wù)何時(shí)恢復(fù)也有一個(gè)合理的預(yù)期, 就會(huì)大大提高他們的滿意度。
知道需要與誰(shuí)、 何時(shí)、 怎么通電話。 溝通方案的框架應(yīng)該提前準(zhǔn)備好草案。 針對(duì)每種類(lèi)型的災(zāi)難,都應(yīng)該提前準(zhǔn)備好溝通計(jì)劃, 包括與誰(shuí)、 何時(shí)、 如何溝通。
客戶(hù)自配置與自助
客戶(hù)自配置可以大大降低成本, 同時(shí)還能提升客戶(hù)滿意度。 如果客戶(hù)可以簡(jiǎn)單地通過(guò)打開(kāi)網(wǎng)頁(yè),輸入所需數(shù)據(jù), 然后就可以開(kāi)始使用服務(wù),這會(huì)比他需要打電話然后在呼叫處理隊(duì)列里浪費(fèi)大量時(shí)間, 滿意度要高地多。 我們一直覺(jué)得主要的移動(dòng)運(yùn)營(yíng)商因?yàn)橐恢蔽礊槟切┎辉钢码娍蛻?hù)服務(wù)的人們提供自助服務(wù), 錯(cuò)過(guò)了一個(gè)既節(jié)省成本又可以提高客戶(hù)滿意度的機(jī)會(huì)。
總結(jié)
對(duì)于大規(guī)模互聯(lián)網(wǎng)服務(wù)來(lái)說(shuō), 降低運(yùn)維成本和提高服務(wù)可靠性始于編寫(xiě)運(yùn)維友好的服務(wù)。 在本文中,我們定義了何謂運(yùn)維友好, 并總結(jié)了來(lái)自于從事大規(guī)模服務(wù)的工程師在服務(wù)設(shè)計(jì)、 部署、 開(kāi)發(fā)和運(yùn)維方面的最佳實(shí)踐。