天天看點

大規模服務設計部署經驗談(2) | 整體服務設計(2.6)

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         了解網絡的設計。

提早進行測試,了解機櫃内的伺服器之間、跨櫃的伺服器之間以及跨資料中心之間有哪些負載。應用程式開發人員必須了解網絡的設計,且設計應當盡早交給來自營運團隊的網絡專員稽核。