大規模服務設計部署經驗

大規模服務設計部署經驗談
本文中提出的最佳實踐,來自於作者多年大規模服務設計和部署的經驗,爲設計、開發對運營友好的服務提供了一系列良好的解決方案。
■ 文/James Hamilton 譯/賴翥翔
1 引言
本文就設計和開發運營友好的服務的話題進行總結,得出一系列最佳實踐。設計和部署大規模服務是一個高速發展的領域,因而隨着時間的流逝,任何最佳實踐集合都可能成熟並完善。我們的目的是爲了幫助人們:
l快速交付運營友好的服務;
l避免清早電話鈴聲的騷擾,幫助備受運營不友好的服務侵擾的客戶儘量擺脫窘境。
這篇論文是我們在過去的20年中在大規模以數據爲中心的軟件系統和互聯網級大規模服務的智慧結晶,包括Exchange Hosted Services 團隊、Microsoft Global Foundation Services
Operations團隊以及Windows Live! 平臺多個團隊的經驗。這些貢獻經驗的服務中,有不少規模已經增長到擁有超過二億五千萬名用戶。同時,本論文也大量吸取了加州大學伯克利分校
在面向恢復計算(Recovery Oriented Computing)方面取得的成果和斯坦福大學在只崩潰軟件(Crash-Only Software)方面的研究經驗。
Bill Hoffman爲本論文貢獻許多最佳實踐。此外,他還提出三條簡單原則,值得大家在進入正題之前進行考量:
1. 做好發生故障的心理準備。
2. 保持簡單化。
3. 將所有的工作自動化。
這三條原則形成了貫穿後續討論的主軸。
本文的十個小節涵蓋了設計和部署運營友好服務所必須做到的各個方面。它們是:整體服務設計;以自動化和預置(Provisioning)爲目標進行設計;依賴關係管理;發佈週期及測試;硬件的選擇和標準化;運營和容量規劃;審覈、監控和警報;體面降級和管理控制;客戶及媒體溝通計劃;以及客戶自我預置和自我幫助。
2 整體服務設計
一直以來,人們都相信80%的 運營問題源於設計和開發,因此本節關於整體服務設計的內容篇幅最長,也最重要。系統出故障時,人們很自然傾向於首先去審視運營工作,因爲這是問題實際產生 的地方。不過,絕大多數運營問題都可以歸因於設計和開發,或者最適合在設計和開發中解決。隨後的內容凸顯一個共識,即在服務領域,將開發、測試和運營嚴格 分離不是最有效的方式。在環顧衆多服務之後, 我們發現了這樣一個趨勢——管理的低成本與開發、測試和運營團隊間協作的緊密程度密切相關。
除了在這裏討論的服務設計最佳實踐以外,隨後一節“以自動化管理和預置爲目標進行設計”對服務設計也有實質性的影響。有效的自動化管理和預置通常以一個受限的服務模型來實現。簡單是高效率運營的關鍵,
這是貫穿本文重複出現的主題。在硬件選擇、服務設計和部署模型上的理性約束,是降低管理成本和提高服務可靠性的強心針。
在運營友好的基礎原則中,爲整體服務設計帶來最大影響的幾條包括:
2.1設計時爲故障做好準備(Design for failure)。
在開發包含多個協同運作的組件的大型服務時,這是一條核心概念。這些組件會有故障發生, 而且故障的產生很頻繁。它們之間不會總是穩定地協作,也不會單獨出現故障。一旦服務的規模達到10,000臺以上的服務器和50,000塊以上的磁盤,每天就會有多次故障發生。如果一有硬件故障產生就得采取緊急措施來應對,那麼服務就無法以合理的成本可靠地伸縮。整個服務必須有承受故障而無須人工干預的能力。故障恢復的步驟必須非常簡單,而且這些步驟應當進行頻繁測試。斯坦福大學的Armando Fox 主張說,對故障恢復步驟進行測試的最佳方法,就是絕對不要用正常方式使服務停機,用粗暴的方式讓它停轉就可以了。乍聽起來怎麼做是違背直覺的,但是如果沒有頻繁使用故障步驟,那麼它們在真正臨陣時就可能潰不成軍 。
2.2冗餘和錯誤恢復(Redundancy and fault recovery)。
大型機模型是指購買一臺價高塊頭大的服務器。大型機擁有冗餘的電源供應,CPU可以熱交換,而且總線架構也超乎尋常,使得這樣一個緊密耦合的系統能夠有可觀的I/O吞吐量。這樣的系統,最明顯的問題就是它們的成本;而且即便有了所有這些費用高昂的設計,它們仍然不夠可靠。爲了達到99.999%的可靠性,冗餘是必須存在的。實際上,在一臺機器上實現49的可靠性都是相當困難的。這個概念在整個業界都耳熟能詳,不過,將服務構建在脆弱而又非冗餘的數據層之上的現象,到目前爲止都屢見不鮮。要保證設計的服務其中的任何系統可以隨時崩潰(或者因爲服務原因被停止)但又仍然能符合服務水平協定(Service Level Agreement, 簡稱SLA),是需要非常仔細的設計的。保證完全遵守這項設計原則的嚴格測試(acid test) 步驟如下:首先, 運營團隊是否有意願並且有能力隨時讓任意一臺服務器停機並且不會讓負載被榨乾?如果答案是確定的,那麼肯定存在同步冗餘(無數據丟失)、故障偵測和自動接管。我們推薦一條普遍使用的設計方法,用於查找和糾正潛在的服務安全問題:安全威脅建模(Security Threat Modeling)。在安全威脅建模中,我們要考慮每一條潛在的安全威脅,並且相應實現恰當的緩和方案。同樣的方法也適用於以錯誤適應和恢復爲目標的設計。
將 所有可以想象到的組件故障模式及其相應組合用文檔記錄下來。要保證服務在每個故障發生後都能繼續運行,且不會在服務質量上出現不可接受的損失;或者判斷這 樣的故障風險對於這樣一個特定的服務是否可以接受(例如,在非地理冗餘的服務中損失掉整個數據中心)。我們可能會認定某些非常罕見的故障組合出現的可能性 微乎其微,從而得出確保系統在發生這種故障之後還能繼續運行並不經濟的結論。但是,在做這樣的決定時請謹慎從事。在運行數以千計的服務器的情況下,每天都 會有幾百萬種組件故障產生的可能,這時那些事件的“罕見”組合亮相的頻繁程度,足以讓我們瞠目結舌。小概率組合可能變成普遍現象。
2.3廉價硬件切片(Commodity hardware slice)。
服務的所有組件都應當以廉價硬件切片爲目標。例如,存儲量輕的服務器可以是雙插槽的24 核的系統,帶有啓動磁盤,價格在1,0002,500 美元之間;存儲量大的服務器則可以是帶有1624個磁盤的類似服務器。主要的觀察結果如下:
l大型的廉價服務器集羣要比它們替代的少數大型服務器便宜得多;
l服務器性能的增長速度依然要比I/O性能的增長速度快很多,這樣一來,對於給定容量的磁盤,小型的服務器就成爲了更爲穩定的系統;
l電量損耗根據服務器的數量呈線性變化,但隨系統時鐘頻率按立方級別變化,這樣一來性能越高的機器運營成本也越高;
l小型的服務器在故障轉移(Fail over)時隻影響整體服務工作負荷的一小部分。
2.4單版本軟件(Single-version software)。
使某些服務比多數打包產品開發費用更低且發展速度更快的兩個因素是:
l軟件只需針對一次性的內部部署。
l先 前的版本無須得到十年的支持——針對企業的產品正是如此。相對而言,單版本軟件更容易實現,附帶客戶服務,特別是無須費用的客戶服務。但是在向非客戶人員 銷售以訂閱爲基礎的服務時,單版本軟件也是同樣重要的。企業通常習慣在面對他們的軟件提供商時擁有重要的影響力,並且在部署新版本時(通常是個緩慢的過 程),他們會習慣性想去掌握全部的控制權。這樣做會導致他們的運營成本和支持成本急劇上升,因爲軟件有許多版本需要得到支持。最經濟型的服務是不會把對客 戶運行的版本的控制權交給他們的,並且通常只提供一個版本。要把握好單一版本軟件的產品線,必須:
l注意在每次發佈之間不要產生重大的用戶體驗變更。
l願意讓需要相應級別控制能力的客戶可以在內部託管,或者允許他們轉向願意提供這類人員密集型支持服務的應用服務提供商。
2.5多重租賃(Multi-tenancy)。
多重租賃是指在同一個服務中爲該服務的所有公司或最終用戶提供主機服務,且沒有物理上的隔離;而單一租賃(Single-tenancy)則是將不同組別的用戶分離在一個隔離的集羣中。主張多重租賃的理由基本上和主張單版本支持的理由一致,且它的基礎論點在於提供從根本上成本更低、構建在自動化和大規模的基礎之上的服務。
回顧起來,上面我們所展示的基本設計原則和思考如下:
l設計時爲故障做好準備
l實現冗餘和錯誤恢復
l依靠廉價硬件切片
l支持單一版本軟件
l實現多重租賃
我們約束服務設計和運營的模型,以此最大化自動化的能力,並且減少服務的總體成本。在這些目標和應用服務提供商或IT 外包商的目標之間,我們要劃一道清楚的界限。應用服務提供商和IT外包商往往人員更加密集,並且更樂於運行面向客戶的複雜配置。
2.6設計運營友好的服務的實踐
設計運營友好的服務更具體的最佳實踐包括:
2.6.1快速服務健康測試。
這是構建驗證測試的服務版本。這是一個嗅探型測試,可以快速在開發者的系統上運行,以保證服務不會以獨立方式出錯。要保證所有的邊界條件都被測試到,是不可能的,但如果快速健康測試通過的話,那麼代碼就可以檢入了。
2.6.2在完整的環境中開發。
開發人員不但應當對他們的組件進行單元測試,而且還要對出現組件變更的整個服務進行測試。要高效實現這個目標,必須得有單服務器的部署,以及前一條最佳實踐——快速的服務健康測試。
2.6.3對下層組件的零信任。
設想下層組件會出現故障,並且確保組件會有能力恢復並繼續提供服務。恢復的技巧和服務相關,但常見的技巧包括:
l在只讀模式中依靠緩存的數據繼續運轉;
l在服務訪問故障組件的冗餘拷貝的短暫時間內,繼續向用戶羣一小部分的所有人提供服務。
2.6.4不要把同一個功能構建在多個組件中。
預見未來的交互是一件極其困難的事情,如果不慎引入冗餘的代碼,那麼將來就不得不在系統的多處做修復。服務的增長和發展是很快的,稍不留神代碼的質量就會很快惡化。
2.6.5不同的集羣之間不能互相影響。
大多數服務由小型集合或者系統的子集羣組成,它們之間相互協作,共同提供服務,其中每個小型集合都可以相對獨立地運作。每個小型集合應達到接近100%的獨立程度,且不會有跨羣的故障。全局服務,甚至包括冗餘,是故障的中心點。有時候,這樣的問題是不可避免的,但還是要設法保證每個集羣都擁有各自所需的資源。
2.6.6允許(少量)在緊急情況的人工干預
見場景是在災難性事件或者其他緊急情況下移動用戶數據。把系統設計成完全無須人工交互,但也要清楚小概率事件可能會發生,其中組合的故障或者未預期的故障都會需要人工交互。這些事件是會發生的,而在這些情況下,操作員的錯誤往往是導致災難性數據丟失的常見來源。一名在半夜2點 頂壓工作的運營工程師可能會犯錯誤。將系統設計成一開始在多數情況下無須運營幹預,但請和運營團隊協作制定在他們需要進行干預時的恢復計劃。比起將這些計 劃寫進文檔,變成多步驟易出錯的過程,更好的辦法是把這些規則寫成腳本,並在生產環境中進行測試,以確保它們正常工作。沒有經過產品環境試驗的代碼是不可 行的,因此運營團隊應當定時指揮使用這些工具進行“防火演習”。如果演習的服務可用性風險非常高,那麼可以認爲之前在工具的設計、開發和測試上的投資不 足。
2.6.7保持一切簡單健壯。
複雜的算法和組件交互會給調試和部署帶來成倍困難。簡單到近乎傻瓜式的結構在大規模服務中幾乎總是更勝一籌, 因爲在複雜的優化工作交付之前, 交互中故障模式的數量早就足以磨滅人們的信心。通常我們的慣例是, 能夠帶來一個數量級以上改善的優化工作才值得考慮, 而只有百分之幾或者甚至於只是低係數級別的提升,就不值得了。
2.6.8全面推進准入控制。
所 有良好的系統會在設計時開門見山地引入許可控制,這樣符合一條長期以來爲人們所認可的原則,那就是避免將更多的工作引入一個已經過載的系統,要比持續接受 工作然後開始翻來覆去地檢查好一些。在服務入口引入某些形式的節流或者准入控制是很常見的做法,但在所有的主要組件邊界上都應該有準入控制。工作性質的變 更最終會導致子組件的過載,即使整體服務仍然運行在可接受的負載級別。總體的慣例就是嘗試採用優雅降級的方式,而不用在統一給所有用戶低質量服務之前進行 硬停機並阻斷服務的入口。
2.6.9給服務分區。
分區應當可以無限調整,並且高度細粒度化,並且不受任何現實實體(人、集合等)的限制。如果按公司分區,那麼對於大的公司,就有可能超過單個分區的規模;而如
果按名稱前綴進行分區,那麼例如所有以P打頭的最終一臺服務器就可能會裝不下。我們推薦在中間層使用一張查詢表,將細粒度的實體,通常是在設計大規模服務的目標和應用服務提供商或IT外包商的目標之間,要劃一道清楚的界限。應用服務提供商和IT 外包商往往人員更加密集,並且更樂於運行面向客戶的複雜配置。
用戶,映射到其數據相應被管理的系統上。這些細粒度的分區隨後就可以自由在服務器之間移動。
2.6.10理解網絡的設計。
提早進行測試,瞭解機櫃內的服務器之間、跨櫃的服務器之間以及跨數據中心之間有哪些負載。應用程序開發人員必須理解網絡的設計,且設計應當儘早交給來自運營團隊的網絡專員審覈。
2.7對吞吐量和延遲進行分析。
應 當對核心服務的用戶交互進行吞吐量和延遲的分析,從而瞭解它們的影響。結合其他運營操作,比如定期數據庫維護、運營配置(加入新用戶,用戶遷移)和服務調 試等,進行吞吐量和延遲的分析。這樣做對於捕捉由週期性管理任務所帶動的問題是頗有裨益的。對於每個服務,都應當形成一個度量標準,用於性能規劃,比如每 個系統的每秒用戶訪問數,每個系統的併發在線人數,或者某些將關聯工作負載映射到資源需求的相關度量標準。
2.8把運營的實用工具作爲服務的一部分對待。
把運營的實用工具作爲服務的一部分對待。由開發、測試、項目管理和運營所產生的運營實用工具應當交給開發團隊進行代碼審查,提交到主源碼樹上,用同一套進度表跟蹤,進行同樣的測試。最頻繁出現的現象是,這樣的實用工具對於任務有至關重要的影響,但幾乎都沒有經過測試。
2.9理解訪問模式。
理 解訪問模式。在規劃新特性時,一定要記得考慮它們會給後端存儲帶來哪些負載。通常,服務模型和服務開發人員與存儲抽象得非常開,以至於他們全然忘記了它們 會給後端數據庫帶來的額外負載。對此的最佳實踐把它作爲規範建立起來,裏面可以有這樣的內容:“這項功能會給基礎結構的其他部分帶來什麼樣的影響?”然後 在這項特性上線之後,對它進行負載的測量和驗證。
2.10讓所有工作版本化。
做好在混合版本的環境中運行的準備。我們的目標是運行單版本的軟件,但是多個版本可能會在首次展示和生產環境測試的過程中並存。所有組件的n 版和n+1版都應當能夠和平共存。
2.10.1保持最新發布版的單元/功能測試。
這些測試是驗證n1 版本的功能是否被破壞的重要方法。我們推薦大家更進一步,定期在生產環境中運行服務驗證(後面會詳細介紹)。
2.10.2避免單點故障。
單點故障的產生會導致整個服務或者服務的某些部分停工。請選擇無狀態的實現。不要將請求或者客戶端綁定在特定的服務器上,相反,將它們負載均衡在一組有能力處理這樣負載的服務器上。靜態哈希或者任何靜態的服務器負載分配都會時不時遭受數據和/ 或 查詢傾斜問題的困擾。在一組機器可以互換時,要做到橫向伸展是非常容易的。數據庫通常會發生單點故障,而數據庫伸縮仍然是互聯網級大規模服務的設計中最爲 困難的事情之一。良好的設計一般會使用細粒度的分區,且不支持跨分區操作,以在多臺數據庫服務器之間進行高效伸展。所有的數據庫狀態都會進行冗餘存儲(至 少在一臺)完全冗餘的熱待機服務器上,並且在生產環境中會頻繁進行故障轉移測試。
3 自動管理和預置
許多服務編寫的目的是爲了在故障時向運營部門發出警報,以得到人工干預完成恢復。這種模式凸顯出在24 x 7 小時運營人員上的開支問題;更重要的是,如果運營工程師被要求在充滿壓力的情況下做出艱難的決定,那麼有20%的 可能他們會犯錯誤。這種模式的代價高昂,容易引入錯誤,而且還會降低服務的整體可靠性。然而,注重自動化的設計會引入明顯的服務模型約束。比如說,當前某 些大型服務依靠的數據庫系統,會以異步方式複製到次級備份服務器,因爲複製以異步方式完成,在主數據庫無法服務請求後,故障轉移到次級數據庫會引起部分客 戶數據丟失。然而,不把故障轉移到次級數據庫,則會引起數據被儲存在故障服務器上的用戶面臨服務停工。在這種情況下,要自動化故障轉移的決策就很困難了, 因爲這個決策依賴於人爲判斷,以及對數據損失量和停機大致時長相比的準確估計。注重自動化設計出的系統會在延遲和同步複製的吞吐量開銷上付出代價。在做到 這一步以後,故障轉移變成了一個很簡單的決策:如果主服務器宕機,將請求轉到次服務器上。這種方式更適用於自動化,而且被認爲更不容易產生錯誤。在設計和 部署後將服務的管理過程自動化可能是一件相當具有難度的工作。成功的自動化必須保證簡單性,以及清晰並易於確定的運營決策;這又要依靠對服務的謹慎設計, 甚至在必要時以一定的延遲和吞吐量爲代價作出犧牲,讓自動化變得簡單。通常這樣的折中方案並不容易確定,但是對於大規模服務來說在管理方面的節約可能不止 數量級。事實上,目前根據我們的觀察,在人員成本方面,完全手動管理的服務和完全自動化的服務之間的差別足足有兩個數量級。注重自動化的設計包含以下最佳 實踐:
3.1可以重啓動,並保持冗餘。
可以重啓動,並保持冗餘。所有的操作都必須可以重新啓動,並且所有持久化狀態也必須冗餘存儲。
3.2支持地理分佈
支持地理分佈。所有大規模服務都應當支持在多個託管數據中心運行。我們所描述的自動化和絕大多數功效在無地理分佈的情況下仍是可行的。但缺乏對多服務中心部署方式的支持, 會引起運營成本顯著提升。沒有了地理分佈, 很難使用一個數據中心的空閒容量來減緩另外一個數據中心所託管的服務的負載。缺乏地理分佈是一項會導致成本提高的運營約束。
3.3自動預置與安裝。
自動預置與安裝。手動進行預置和安裝是相當勞民傷財的,故障太多,而且微小的配置差異會慢慢在整個服務中蔓延開來,導致問題的確定越來越困難。
3.4將配置和代碼作爲整體。
將配置和代碼作爲整體。請確保做到:
l開發團隊以整體單元的形式交付代碼和配置;
l該單元經過測試部門的部署,並嚴格按照運營部門將會部署的方式;
l運營部門也按照整體單元的方式部署。通常說,將配置和代碼作爲一整個單元處理並且只把它們放在一起修改的服務會更可靠。
3.5生成環境的變更必須審覈和記錄
如 果配置必須在生產環境中變更,那麼請保證所有的變更都要產生審覈日誌記錄,這樣什麼東西被修改,在什麼時候被誰修改,哪些服務器受到影響,就一目瞭然了。 頻繁掃描所有的服務器,確保它們當前的狀態與預期狀態相符。這樣做對捕獲安裝和配置故障頗有裨益,而且能在早期偵測到服務器的錯誤配置,還能找到未經審覈 的服務器配置變更。
3.6管理服務器的角色或者性質,而不是服務器本身
管理服務器的角色或者性質,而不是服務器本身。每個系統的角色或性質都應當按需要支持儘可能多或少的服務器。
3.7多系統故障是常見的。
多系統故障是常見的。請做好多臺主機同時發生故障的準備(電源、網絡切換和首次上線)。遺憾的是,帶有狀態的服務必須得注意它們的拓撲分佈。有相互聯繫的故障一直以來都是不可避免的。
3.8在服務級別上進行恢復。
在服務級別上進行恢復。在服務級別處理故障,相比軟件底層來說,其中的服務執行上下文更加完整。例如,將冗餘納入服務當中,而不是依靠較低的軟件層來恢復。
3.9對於不可恢復的信息,絕對不要依賴於本地存儲。
對於不可恢復的信息,絕對不要依賴於本地存儲。保證總是複製所有的非瞬時服務狀態。
3.10保持部署的簡單性
保持部署的簡單性。文件複製是最理想的方式,因爲這樣能帶來最大的部署靈活性。最小化外部依賴性;避免複雜的安裝腳本;避免任何阻止不同組件或者同一個組件不同版本在同一臺機器運行的情況。
3.11定期使服務停轉
定 期使服務停轉。停掉數據中心,關閉櫃式服務器,斷掉服務器電源。定期進行受控的關閉操作,能夠主動暴露出服務器、系統和網絡的缺陷。沒有意願在生產環境中 測試的人,實際上是還沒有信心保證服務在經歷故障時仍能繼續運轉。此外,若不進行生產測試,在真正出事時,恢復不一定能派上用場。■

4 依賴管理
在大規模服務中,依賴管理這個話題通常得不到應有的關注。一般的準則是,對於小型組件和服務的依賴關係,對於判斷管理它們的複雜性來說,並不足以節約成本。在以下情況中,依賴關係存在重要意義:
1. 被依賴的組件在大小和複雜度上有重要價值;
2. 被依賴的服務在作爲單一的中央實例時存在價值。
第一類的例子有存儲和一致性算法(consensus algorithm) 的實現。
第二類的例子包括身份和羣組管理系統。這些系統的整體價值在於它們是一個單一且共享的實力,因此使用多實例來避免依賴關係就不是可選方案。假定要根據上面的標準判斷依賴關係,那麼用來管理它們的最佳實踐有:
4.1爲延遲做好準備。
爲 延遲做好準備。對外部組件的調用可能需要很長時間才能完成。不要讓一個組件或者服務中的延遲在完全不相關的領域中引發延遲;確保所有的交互都存在長度合適 的超時時長,避免資源阻塞更長的時間。運營等冪性允許請求在超時後重啓,即便這些請求可能已經部分或完全完成。確保所有的重啓操作都得到報告,並給重啓操 作設定界限,從而避免反覆故障的請求消耗更多的系統資源。
4.2隔離故障。
網站的架構必須能防止層疊的故障,要總是“快速失敗(fail fast)”。當依賴服務出現故障時,把這些服務標註爲停機,並停止使用這些服務,以避免線程因等待故障組件而阻塞。
4.3使用已經交付的歷經考驗的組件。
使用已經交付的歷經考驗的組件。歷經考驗的技術通常總是要比大膽前衛地走在潮流尖端運行要好很多。穩定的軟件要優於新版本的早期,不管新特性如何有價值。這條原則也適用於硬件。批量生產的穩定硬件,往往要比從早期發佈的硬件所獲得的些許性能提升要有價值得多。
4.4實現跨服務的監控和警報。
實 現跨服務的監控和警報。如果服務中有一個附屬服務過載,那麼被依賴的服務就必須瞭解這個情況,並且如果服務無法自動備份,那麼必須發送警報。如果運營部門 無法快速地解決這個問題,那麼服務就得設計得能容易迅速地聯繫到兩個團隊的工程師。所有相關的團隊都應當在附屬團隊中安排工程聯絡人。
4.5附屬服務需要同一個設計點。
附屬服務需要同一個設計點。附屬的服務和附屬組件的生產者至少必須遵循與所屬服務相同的SLA(服務水平協議)。
4.6對組件解耦。
對組件解耦。在所有可能的地方保證在其他組件故障時,組件可以繼續運行,可能在一個降級的模式中。例如,比起在每一個連接上重新驗證,維護一個Session鍵值,並且無論連接狀況如何,每過N小時就刷新這個鍵值會更好些。在重新建立連接時,只使用現有的Session 鍵值。這樣的話在驗證服務器上的負載就會更加一致,而且也不會在臨時網絡故障和相關事件之後的重新連接過程中出現登錄高峯期的情況。
5 發佈週期及測試
在生產環境中進行測試是一件很現實的事情,必須成爲所有Internet 級服務所必須的質量保證方式之一。在儘可能( 可 以掏得起錢)的情況下,絕大多數服務都應當有至少一個與生產環境相似的測試實驗室,並且所有優秀的工程師團隊應當使用生產級的負載,以反映現實的方式測試 服務器。不過,我們的經驗是,這些測試實驗室即便模擬得再好,也絕不可能百分之百的逼真;它們至少總是會在一些細微的方式上和生產環境有所差別。由於這些 實驗室在真實性上接近生產系統,因此相應的費用也呈漸進趨勢,在部署互聯網級大規模服務時,有關依賴管理和發佈週期及測試方面的經驗和最佳實踐在本文中得 以體現。新的服務發佈版本可以順着標準單元測試、功能測試和生產測試實驗室測試一路走下來,一直進入受限的生產環境作爲最後的測試階段。
快 速逼近生產系統的開支。與此不同,我們推薦讓新的服務發佈版本順着標準單元測試、功能測試和生產測試實驗室測試一路走下來,一直進入受限的生產環境作爲最 後的測試階段。顯然,我們不想讓無法正常工作並給數據一致性帶來風險的軟件進入生產環境,因此這就不得不小心翼翼地實施。下面的原則一定要遵守:
1. 生產系統必須有足夠的冗餘,以保證在災難性的新服務故障發生時,能夠快速地恢復到原來的狀態;
2. 必須讓數據損壞或者狀態相關的故障極難發生(一定要首先通過功能測試);
3. 故障一定要能檢測得到,並且開發團隊(而不是運營團隊)必須監控受測代碼的系統健康度;
4. 必 須可以實現對所有變更的回滾操作,並且回滾必須在進入生產環境之前經過測試。這聽起來有點讓人心驚膽戰。不過我們發現,使用這個技術實際上能夠在新服務發 布時提升客戶體驗。與儘可能快地進行部署的做法不同,我們在一個數據中心中將一個系統放到生產環境數天。隨後在每個數據中心內把新系統引入生產環境。接 着,我們會將整個數據中心帶入生產環境。最後,如果達到了質量和性能的目標,我們就進行全局部署。這種方式可以在服務面臨風險之前發現問題,事實上還可以 通過版本過渡提供更優秀的客戶體驗。一錘定音的部署是非常危險的。我們青睞的另一種可能違反直覺的方式是,在每天正午而不是半夜部署。在晚上部署,出現錯 誤的風險更高,而且在半夜部署時如果有異常情況突然發生,那麼能處理這些問題的工程師肯定會少些。這樣做的目標是
爲了使開發和運營團隊與整體系統的互動最小化,尤其在普通的工作日之外,使得費用得到削減的同時,質量得到提高。對於發佈週期和測試的最佳實踐包括:
5.1經常性地交付。
經常性地交付。直覺上講,人們會認爲更頻繁地交付難度要更大,而且會錯誤頻出。然而我們發現,頻繁的交付中突兀的變更數量很少,從而使得發佈的質量變得更高,並且客戶體驗更棒。對一次良好的發佈所進行的酸性測試,用戶提供可能會有所變化,但是關於可用性和延遲的運營
問題的數量應當在發佈週期中不受改變。我們會喜歡三個月一次的交付,但也可以有支持其他時長的論調。我們從心底認爲,標準最終會比三個月更少,並且有許多服務已經是按周交付的了。比三個月更長的週期是很危險的。
5.2使用生產數據來發現問題。
使用生產數據來發現問題。在大規模系統中的質量保證,是個數據挖掘和可視化的問題,而不是一個測試問題。每個人都必須專注於從生產環境的海量數據中獲得儘可能多的信息。這方面的策略有:
l可度量的發佈標準。定義出符合預期用戶體驗的具體標準, 並且對其進行持續監控。如果可用性應當爲99%, 那麼衡量可用性是否達到目標。如果沒有達到, 發出警報並且進行診斷。
l實時對目標進行調優。不要停頓下來考慮到底目標應當是99%、99.9%還是任何其他目標,設定一個可以接受的目標,然後隨着系統在生產環境中穩定性的建立,讓目標漸進式地增長。
l一直收集實際數據。收集實際的度量,而不是那些紅紅綠綠的或者其他的報表。總結報表和圖像很有用,不過還是需要原始數據用來診斷。
l最小化“ 假陽性(falsepositive)”現象。在數據不正確時,人們很快就不再關注它們。不要過度警報,真是很重要的,否則運營人員會慢慢習慣於忽略這些警報。這非常重要,以至於把真正的問題隱藏成間接損害常常是可以接受的。
l分析趨勢。這個可以用來預測問題。例如,當系統中數據移動的速度有異於往常的時候,常常能夠預測出更大的問題。這時就要研究可用的數據。
l使系統健康程度保持高度透明。要求整個組織必須有一個全局可用且實時顯示的系統健康報告。在內部安置一個網站,讓大家可以在任意時間查看並瞭解當前服務的狀態。
l持續監控。值得一提的是,人們必須每天查看所有數據。每個人都應當這麼做,不過可以把這項工作明確給團隊的一部分人專職去做。
5.3在設計開發上加大投入。
在 設計開發上加大投入。良好的設計開發可以使運營需求降到最小,還能在問題變成實際運營矛盾之前解決它們。非常常見的一個現象就是組織不斷給運營部門增加投 入,處理伸縮問題,卻從沒花時間設計一套伸縮的可靠架構。如果服務一開始沒有進行過宏偉的構思,那麼以後就得手忙腳亂地追趕了。
5.4支持版本回滾。
支持版本回滾。版本回滾是強制的,而且必須在發佈之前進行測試和驗證。如果沒有回滾,那麼任何形式的產品級測試都會存在非常高的風險。回覆到先前的版本應該是一個可以在任意部署過程中隨時打開的降落傘扣。
5.5保持前後版本的兼容性
保持前後版本的兼容性。這一點也是至關緊要的,而且也前面一點關係也非常密切。在組件之間更改文件類型、接口、日誌/ 調試、檢測(instrumentation)、監控和聯繫點,都是潛在的風險來源。除非今後沒有機會回滾到之前的老版本的可能,否則不要放棄對於老版本文件的支持。
5.6單服務器部署。
單 服務器部署。這既是測試的需求也是開發的需求,整個服務必須很容易被託管到單一的系統中。在對於某些組件單服務器無法實現的地方(比如說一個對於外部、非 單箱的可部署服務),編寫模擬器來使單服務器測試成爲可能。沒有這個的話,單元測試會的難度會很大,而且不會完全覆蓋到實際條件。而且,如果運行完整的系 統很困難的話,開發人員會傾向於接受從組件的角度看問題,而不是從系統的角度。
5.7針對負載進行壓力測試。
針對負載進行壓力測試。使用兩倍(或者更多倍的)負載來運行生產系統的某些小部分,以確保系統在高於預期負載情況下的行爲得到了解,同時也確保系統不會隨着負載的增加而瓦解。
5.8在新發布版本之前進行功能和性能測試。
在新發布版本之前進行功能和性能測試。在服務的級別上這麼做,並針對每個組件這麼做,因爲工作負載的特徵會一直改變。系統內部的問題和降級現象必須在早期捕獲。
5.9表象性且迭代地進行構建和部署。
表 象性且迭代地進行構建和部署。在開發週期中早早地把完整服務的骨架先搭建起來。這個完整服務可能幾乎做不了什麼,也可能在某些地方出現偏差,但是它可以允 許測試人員和開發人員更有效率,而且也能讓整個團隊在一開始就從用戶的角度進行思考。在構建任何一個軟件系統時,這都是一個好方法。不對,對於服務來說這 尤爲重要。
5.10使用真實數據測試。
使用真實數據測試。將用戶請求和工作量從生產到測試環境分門別類。選擇生產數據並把它放到測試環境中。產品形形色色的用戶,在發現bug 的時候總是顯得創意無窮。顯然,隱私承諾必須保持,使得這樣的數據永遠不會泄漏回到產品環境中,這是至關緊要的。
5.11運行系統級的驗收測試。
運行系統級的驗收測試。在本地運行的測試提供可以加速迭代開發的健康測試。要避免大量維護費用,這些測試應當放在系統級別。
5.12在完全環境中做測試和開發
在完全環境中做測試和開發。把硬件放在一邊,在專注的範圍內測試。作重要的是,使用和在這些環境中的生產條件下同樣的數據集合和挖掘技術,以保證投資的最大化。■(中結束)

6 運營和功能計劃
要高效地運營服務,關鍵在於讓構建的系統有效地消除運營團隊的絕大部分管理交互。這樣做的目標,是讓一個高度可靠的24 x 7 小時運行的服務,由一個8 x 5小時工作的運營團隊就足以維護起來。
不過世事難料,一組或者多組系統救火不成,無法恢復上線的事情是時有發生的。在熟知這些可能性的情況下,實現把損壞的系統標爲當機這個過程的自動化。依賴運營團隊手動更新SQL 表 或者使用特別的技術移動數據,都會招致災難。與故障交戰正酣時,往往錯誤也容易迭出。先預估運營團隊需要採取的補救措施,然後預先編寫和測試這些過程。一 般來說,開發團隊必須將緊急恢復措施自動化,而且他們必須對之進行測試。顯然,百密一疏,並非所有故障都能預估到,但通常一小組恢復措施就可以用來恢復多 種類型的故障。從根本上說,要構建並測試可以根據災難的範圍和性質以不同方式使用及結合的“恢復內核”。
恢 復腳本應當在生產環境中進行測試。這裏有一條普適規則,即如果沒經過頻繁測試,什麼程序都無法正常工作,因此不要實現團隊沒勇氣使用的任何東西。如果在生 活環境中測試風險過高,那麼腳本就沒有達到能在緊急情況下使用的標準,或者說在緊急情況下不安全。這裏很關鍵的一點是,災難總是可能發生的,由無法按預期 結果運行的恢復步驟所導致的小問題釀成大災難的例子是屢見不鮮的。要預見到這樣的事件,設計出自動化措施,讓服務回覆正常狀態,而不至於丟失更多數據或損 耗更多正常運行時間。
6.1讓開發團隊承擔責任。
讓開發團隊承擔責任。Amazon也 許是沿着這條道路貫徹得最堅定最矢志不渝的公司了——他們的口號是“你創建就該你管”。這樣的立場也許要比我們會選擇的更堅定一些,但這顯然是一個正確的 大方向。如果不得不頻繁在深更半夜給開發團隊打電話,那麼你就得做出一套自動化方案。如果需要頻繁給運營團隊打電話,那麼通常的反應就是要增加運營團隊的 人手。
6.2只進行軟刪除。
只進行軟刪除。絕不要刪除任何東西,只可以把這些東西標記成刪除狀態。在有新數據進入時,即時將請求記錄下來。每兩週(或者更長時間)保存一份所有操作的歷史記錄,可以有助於從軟件或者管理上的錯誤進行恢復。如果有誰犯了錯誤,忘記在delete 語句加上where 子句(這樣的錯誤以前發生過,以後也可能再犯),那麼數據的所有邏輯拷貝都會被刪除。不管是RAID還 是鏡像都無法防止這樣的錯誤。具備數據恢復的能力,可以讓原來會十分令人窘迫難堪的大問題轉化爲一個小到甚至可以忽略不計的小障礙。對於那些已經做過離線 備份的系統,只需要從上次備份開始記錄進入服務的附加數據就可以了。不過謹慎起見,不管怎麼說我們還是推薦進行更進一步的備份。
6.3跟蹤資源分配。
跟 蹤資源分配。瞭解性能規劃的額外負載所帶來的開銷。每個服務都需要開發出一些使用的度量標準,例如併發在線用戶數量、每秒用戶訪問數或者其它合適的標準。 不管度量標準是什麼,在這個負載度量和所需的硬件資源之間肯定存在一個已知的直接相互關係。估算的負載數字應當由銷售和營銷部門提供,並在性能規劃過程中 爲運營團隊所使用。不同的服務會擁有不同的變更速率,也要求不同的訂購週期。在我們開發過的服務中,我們每90天更新一次市場預報,每30天更新一次性能規劃和訂購一次設備。
6.4每次變更一樣東西
每次變更一樣東西。在出現麻煩時,應當每次只向環境應用一個變更。這條準則看起來顯而易見,但我們也看見過許多場合裏出現多個變更,導致起因和效果不能吻合。
6.5使所有資源都可以配置。
使 所有資源都可以配置。在生產環境中,任何存在變更需求的資源,都應無需經過任何代碼改變,就能在生產環境中進行配置和調優。即使你沒什麼好理由說明爲什麼 某個值會有必要在生產環境中更改,只要實現起來沒什麼難度,還是讓它可變更好些。不應在生產環境中隨意更改這些開關,而應該使用爲生產環境所規劃的配置對 整個系統進行徹底測試。不過,在出現生產環境問題時,比起編碼、編譯、測試再部署代碼變更的過程,進行簡單的配置變更永遠是更加簡單、安全和快速的。
7 審覈、監控和預警
運營團隊不能在部署環境中裝配服務。要在部署過程中付出實質性的努力,以確保系統中的每個組件都可以生成性能數據、健康數據和吞吐量數據等。
在 任何有配置變更發生的時候,都必須在審覈日誌中記錄詳細變更內容、變更人和變更時間。在生產環境出現異常時,第一個要回答的問題就是最近到底進行過哪些變 更。離開了審覈跟蹤,那麼這個答案就是“什麼都沒被改過”,而且情況往往會是,被人們忘掉的就是引發問題的變更。預警是一門藝術。人們總是傾向於對所有事 件都做警報,因爲開發人員認爲這些事件可能值得關注。正是如此,多數服務的第一版通常都會產生長篇累牘的無用預警,結果再也沒
有 人去理睬。要提高效率,每個警報都得說明一個問題,否則運營團隊會慢慢學會對這些警報置之不理。進行互動慢慢跳出需要警報的條件,保證所有關鍵性事件得到 預警,以及在無需採取應對措施時沒有警報。除此之外,要實現正確的預警別無靈丹妙藥。要得到正確的預警標準,有兩條度量標準很有用,也值得嘗試:
一、警報和實際故障比(同時要設定一個較爲接近的目標);
二、沒有相應警報的系統健康問題數量(並設定一個近於0的目標)。
7.1對所有資源進行檢測。
對 所有資源進行檢測。測量通過系統的每一次用戶交互或事務,報告異常情況。嘗試“運行器(人爲的工作負載,用來模擬生產環境中用戶和服務的交互)”也是可以 的,不過這還遠遠不夠。如果只是單獨使用運行器,我們發現需要花費數日才能檢測到一個嚴重錯誤,因爲運行器的標準工作負載也會被繼續良好地處理,接下來還 要再花幾天才能查出原因。
7.2數據是最有價值的資產。
數據是最有價值的資產。如果沒有充分理解正常的操作行爲,那麼要對非正常行爲做出響應就不是件容易的事情。我們需要彙集許多系統內發生的事件信息,才能知道系統是否真的正常運行。許多服務都經歷過災難性故障,而只有電話鈴響起的時候,人們才意識到故障的發生。
7.3從客戶的角度看服務。
從 客戶的角度看服務。進行端到端的測試。雖然單有運行器不夠,但還是需要它們來保證服務器的完整運行。保證例如新用戶登錄這樣重要的複雜過程經過運行器的測 試。避免誤警,如果在某個運行器上的故障沒被當作重要故障,那麼變更測試對象,換到是重要故障的運行器上。重申一下,一旦人們開始對數據視而不見,真正的 損失就會讓人們措手不及。
7.4檢測是生產環境測試所必不可少的。
檢測是生產環境測試所必不可少的。檢測是生產環境測試所必不可少的。要在生產環境中實現安全的測試,就有必要進行全面監控和預警。如果某個組件開始出現故障,就必須快速檢測出來。
7.5延遲是最棘手的問題。
延遲是最棘手的問題。緩慢的I/O,以及尚未出現故障但處理緩慢的現象,都是很好的例子。這些問題發現起來很困難,所以一定要仔細檢測,保證這樣的現象可以檢測出來。
7.6要有足夠的生產環境數據
要有足夠的生產環境數據。爲了發現問題,數據是不可或缺的。在早期就要建立細粒度的監控機制,否則放到後面再翻新成本就高得多了。
我們所依賴的數據中最重要的包括:
l對所有操作使用性能計數器。至少記錄操作的延遲和每秒鐘的操作次數。這些數值突然出現的此消彼長現象,是一個十分危險的信號。
l審 核所有操作。每次有人進行操作之後,尤其是那些明顯的操作,一定要記入日誌。這樣做有兩個目的:首先,可以對日誌進行挖掘,找出用採取的操作類型(在我們 的例子裏是用戶查詢的種類);其次,一旦發現問題,這樣做有助於調試問題。相關視點:如果每個人使用相同的賬號管理系統的話,這麼做帶來不了多少好處。相 反這是一個非常糟的辦法,不過這種情況不多。
l跟蹤所有容錯機制。容錯機制會把故障隱藏起來。每次出現重試、某個數據被一處複製到另一處,以及機器或者服務重啓這類現象時,都要進行跟蹤。要了解容錯機制在何時隱藏了小故障,這樣就可以對這些小故障進行追溯,以防其變成大面積故障。我們曾經碰到過這樣一個問題:一個跨2000臺機器的服務在幾天內慢慢地癱瘓,最後只剩400 臺機器可用,而一開始這個問題卻沒有發現。
l跟蹤對重要實體的操作。爲某個特殊實體的所有重要操作記錄一份“審覈日誌”,不管這個實體是一個文檔,或者一組文檔。在運行數據分析時,常常能在數據中發現異常現象。要了解數據的來源及其經歷的處理過程。到了後期才往項目加入這樣的功能是非常困難的。
l斷言(asserts)。不要吝惜斷言的使用,而且要貫徹在整個產品中。收集因此產生的日誌或者崩潰轉儲(crashdump),並進行調查研究。對於在同一個進程邊界內運行不同服務並且無法使用斷言的系統,要寫下跟蹤記錄。不管哪種實現,都要能夠對錯誤進行標記,頻繁挖掘不同問題的頻率。
l保留歷史記錄。歷史性能和日誌數據對於趨勢的總結和問題的診斷都是非常必要的。
7.7可配置的日誌功能。
可配置的日誌功能。對可配置的日誌功能提供支持,這些日誌記錄可以有選擇性開啓或關閉,以便進行錯誤調試。在故障過程中,如果不得不部署帶額外監控功能的新構建版本是非常危險的。
7.8外部化健康信息,用於監控
外部化健康信息,用於監控。考慮能實現外部監控服務健康程度的方式,並使對生產環境進行監控容易實現。
7.9保證所有報告的錯誤可以應對
保 證所有報告的錯誤可以應對。問題總會發生,系統也總會出錯。如果在代碼中檢測到無法恢復的錯誤,並且在日誌或者報告中歸爲錯誤,那麼錯誤信息應當指出錯誤 可能發生的原因,並提供修復的建議。無法採取應對措施的錯誤報告毫無用處,而且時間一久這些錯誤報告會像“狼來了”一樣被人們忽略,那時候真正的錯誤就可 能被錯過。
7.10啓用生產環境問題的快速診斷。
啓用生產環境問題的快速診斷。
爲診斷提供足夠信息。當問題被標出時,要提供足夠的信息,人們纔可以對其進行診斷;否則門檻會非常高,標註也會被忽略。例如,不要只說“10個查詢都沒返回結果”,還得補上“列表在這裏,還有問題出現的次數”。
證據鏈。保證存在一條貫穿始終的路徑,可供開發人員診斷之用。通常這都是由日誌實現的。
在 生產環境中的調試。我們偏愛這樣的一種模式:系統沒有被包括運營團隊在內的任何人觸碰過,並且調試是通過鏡像快照、內存轉儲並將所得數據發送到生產環境之 外來實現的。當生產環境成爲唯一選擇是,開發人員就是最好的選擇。要確保開發人員得到良好的培訓,知曉生產環境的操作限制。我們的經驗是,系統在生產環境 中動的次數越少,客戶通常也越開心。因此我們推薦,一定要多努一把力,儘量避免接觸生產環境中的系統。
◇ 記 錄所有重要的操作。每次系統執行了重要的操作,特別是對網絡請求和數據修改上,要進行記錄。這既包括用戶發送命令的事件,也包括系統內部的行爲。有了這樣 的記錄,調試問題的時候就會獲益無窮。更重要的是,還可以開發出相應的挖掘工具,用來找出有用的集合,比如用戶的查詢都是什麼樣的(也就是說,用了哪些關 鍵字,有多少關鍵字等等)。
8 優雅降級和許可控制
當發生DoS***或者由於用戶使用模式變化而帶來的負載激增時,服務器需要能實現優雅降級和管理控制。例如,911恐怖襲擊發生後,大多數的新聞服務都發生癱瘓,無法向所有用戶羣體提供任何可用的服務。與此相比,如果能夠將一部分文章可靠地提供給用戶,總比什麼都不能提供好。最佳實踐有兩種:“大紅開關(big red switch)”和許可控制,如果能夠針對服務進行量身定製,作用將會十分強大。
8.1支持“大紅開關”。
支持“大紅開關”。這個概念最初來源於Windows Live Search,它擁有很大的權力。我們對這個概念進行了一定程度的推廣,更事務性的服務與搜索差別迥異。不過這個想法非常有效,而且可以應用於任何地方。一般來說,“大紅開關”是當服務已經或者即將無法滿足SLA時, 採用的一個經過精心設計和測試的措施。將優雅降級比喻成“大紅開關”稍微有些不恰當,但核心意思是指在緊急時刻卸掉非關鍵的負載。“大紅開關”的主要思想 是保證關鍵任務的運行,同時卸掉或者延遲非關鍵的負載。從設計角度來說,這種情況應該不會發生,但在發生緊急情況時不失爲一個好的救火辦法。在緊急情況已 經發生之後再來考慮這些問題是十分危險的。如果有哪個負載可以被加入隊列並延後處理,或者在關掉高級查詢後仍能繼續運行事務系統,那麼這都是作爲“大紅開 關”的理想對象。關鍵在於,判斷在整個系統出現問題時有哪些任務是必不可少的,然後實現並測試在問題出現時關閉非關鍵服務的選項。切記“大紅開關”必須是 可逆的,也就是說當緊急情況解除後,必須保證開關能正確地讓所有的批處理工作和先前被停止的非關鍵任務恢復原狀,這是應當經過測試的。
8.2控制許可
控 制許可。許可控制是另外一個重要的概念。如果都無法對當前的任務進行處理,向系統引入更多的工作負載只會將不好的體驗擴散到更大的用戶羣中。這要如何實現 和系統有關,有些系統實現很容易,有些則比較困難。拿我們上次的郵件處理服務作爲例子,如果系統超過負荷,開始排隊列的話,我們最好是拒絕接受後續郵件進 入系統,然後讓這些郵件在來源處列隊等候。這樣做很有意義並實際上減少了整體服務延遲,主要原因在於一旦隊列在我方形成,系統會處理得更慢。如果我們拒絕 形成隊列,吞吐量也會得以提升。另外一個訣竅是:重要客戶優先於非重要用戶,註冊用戶優先於訪客(但如果是以吸引新訪客作爲商業模式的,另當別論)。
8.3對許可進行計量
對許可進行計量。還有一個無比重要的概念,就是前面所說的許可控制觀點的修改方案。如果系統故障並當機,必須能夠實現逐步恢復用戶使用,並確保系統運行正常。比如先允許1 個用戶進入,然後允許每秒進入10 個用戶,隨後再逐漸放寬限制。對於重新上線或者從嚴重錯誤中恢復過來的系統,應該確保每項服務都有一個細粒度的開關,來實現用戶的緩慢增加,這是至關緊要的。大多數系統的初始版本中很少有包括這項功能。
對於有客戶端的系統,一定會存在一種方式,用來通知客戶端服務器當機,並且告知可能的恢復時間。這樣一方面使客戶端儘可能繼續基於本地數據來運行,另一方面也可以避免客戶端打擾服務器,以便後者更快恢復。這樣同時也給了服務擁有者一個直接和用戶溝通的機會( 見下節),用來調整用戶的期望值。另外一個關於客戶端的技巧是刻意設置擾動(jitter),和自動備份來防止客戶端在同一時刻“撲向”脆弱的服務器。客戶和媒體溝通計劃當系統出錯時需要就發生的延誤和其它相關事項與客戶進行溝通。溝通應當能以可選的方式通過多個渠道完成 :RSSWeb, 還有即時消息等等。另外,對於擁有客戶端的系統,通過客戶端來進行和用戶的溝通也是很有效的。可以告訴客戶端在一定時間內或者特定時間點之前避免訪問服務 器,或者如果支持的話,可以告訴客戶端在離線和緩存的方式運行。客戶端可以把系統狀態告訴用戶,並說明可以預計完整的功能在何時恢復。即使在沒有客戶端的 情況下,比如用戶通過網頁來和系統交互,仍然可以告知用戶系統當前的狀態。當用戶瞭解發生的狀況並對系統的恢復時間有一個合理的期望值,他們的滿意度會大 大提高。系統管理員常常會不自覺地傾向於隱藏系統發生的問題,但是跟據我們的經驗,我們確信,將系統的狀態告知用戶會極大地提高其滿意度。即便是非付費系 統,如果人們知道系統發生了狀況並被告知其何時會恢復,他們放棄使用這項服務的可能性也會減小。某些事件會引發媒體報導。如果這樣的場景有預先備好的應對 方案,那麼會更加真實地反應服務的情況。大量數據丟失或損壞、安全遭到破壞、違反隱私以及服務器長時間當機,這樣的情況都可能引起媒體的關注。事先準備好 一份溝通計劃。清楚電話通知誰,並能主導談話。溝通方案的框架應當事先搭好。應針對每一種事故制定一份溝通方案,內容包括該給誰電話通知、電話時間,還有 如何掌控溝通過程。客戶自預置及自助服務客戶自己進行預置可以大幅度降低成本,同時還能提升客戶滿意度。如果客戶可以訪問網站,輸入所需數據,然後就可以 開始使用服務,那麼他們要比不得不在電話處理隊列中浪費時間開心得多。我們一直認爲,主流移動運營商因爲沒爲那些不想致電客戶支持組的用戶提供自助服務, 錯過了一次拯救並提升客戶滿意度的好機會。
9 結語
要降低大規模互聯網服務的運營成本並改善服務的可靠性,一切從編寫服務時注重運營友好開始。在這篇論文中,我們爲“運營友好”做了詮釋,並根據從事大規模服務的工程師的經驗,總結了服務設計、開發、部署和運營的最佳實踐

10 作 者 簡 介
James Hamilton
是微軟LivePlatform Service團隊的架構師,在微軟有11 年工作經驗, 此前他曾帶領Exchange Hosted Service團隊,該團隊爲超過兩百萬用戶提供Email 相關服務。在微軟的前八年,他曾是SQL Server 團隊成員,並帶領大部分的核心引擎開發團隊。在加入微軟之前,James 曾擔任IBMDB2 UDB 團隊的首席架構師,更早時曾帶領團隊交付IBM的第一個C++ 編譯器。在20 世紀70 年代末、80 年代初,他曾持有汽車機械師和意大利汽車競賽駕駛執照。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章