微服務架構使得能夠經過明肯定義的服務邊界來隔離故障。可是像在每一個分佈式系統中同樣,發生網絡、硬件、應用級別的錯誤都是很常見的。因爲服務依賴關係,任何組件可能暫時沒法提供服務。爲了儘可能減小部分中斷的影響,咱們須要構建容錯服務,來優雅地處理這些中斷的響應結果。創建可靠的系統老是會帶來額外的成本。git
微服務架構將應用程序邏輯移動到服務,並使用網絡層在它們之間進行通訊。這種經過網絡間通訊代替單應用程序內調用的作法,會帶來額外的延遲,以及須要協調多個物理和邏輯組件的系統複雜度。分佈式系統的複雜性增長也將致使更高的網絡故障率。github
微服務體系結構的最大優點之一是,團隊能夠獨立設計,開發和部署他們的服務。他們對服務的生命週期擁有徹底的全部權。這也意味着團隊沒法控制他們依賴的服務,由於它更有可能由不一樣的團隊管理。使用微服務架構,咱們須要記住,提供者服務可能會臨時不可用,因爲其餘人員發行的錯誤版本,配置以及其餘更改等。算法
微服務架構的最大優勢之一是您能夠隔離故障,並在當組件單獨故障時,進行優雅的服務降級。 例如,在中斷期間,照片共享應用程序中的客戶可能沒法上傳新圖片,但仍能夠瀏覽,編輯和共享其現有照片。數據庫
在大多數狀況下,因爲分佈式系統中的應用程序相互依賴,所以很難實現這種優雅的服務降級,您須要應用幾種故障轉移的邏輯(其中一些將在本文後面介紹),覺得暫時的故障和中斷作準備。瀏覽器
Google的網站可靠性小組發現,大約70%的中斷是由現有系統的變化引發的。當您更改服務中的某些內容時,您將部署新版本的代碼或更改某些配置 – 這總有可能會形成故障,或者引入新的bug。緩存
在微服務架構中,服務依賴於彼此。這就是爲何你應該儘可能減小故障並限制它的負面影響。要處理變動中的問題,您能夠實施變動管理策略和自動回滾機制。服務器
例如,當您部署新代碼或更改某些配置時,您應該先小範圍的進行部分的替換,以漸進式的方式替換服務的所有實例。在這期間,須要監視它們,若是您發現它們對您的關鍵指標有負面影響,應當即進行服務回滾,這稱爲「金絲雀部署」。網絡
另外一個解決方案多是您運行兩個生產環境。您始終只能部署其中一個,而且在驗證新版本是否符合預期以後才,將負載均衡器指向新的。這稱爲藍綠或紅黑部署。架構
回滾代碼不是壞事。你不該該在生產中遺留錯誤的代碼,而後考慮出了什麼問題。若是必要,越早回滾你的代碼越好。併發
實例因爲出現故障、部署或自動縮放的狀況,會進行持續啓動、從新啓動或中止操做。它可能致使它們暫時或永久不可用。爲避免問題,您的負載均衡器應該從路由中跳過不健康的實例,由於它們當前沒法爲客戶或子系統提供服務。
應用實例健康情況能夠經過外部觀察來肯定。您能夠經過重複調用GET /health
端點或經過自我報告來實現。如今主流的服務發現解決方案,會持續從實例中收集健康信息,並配置負載均衡器,將流量僅路由到健康的組件上。
自我修復能夠幫助應用程序從錯誤中恢復過來。當應用程序能夠採起必要步驟從故障狀態恢復時,咱們就能夠說它是能夠實現自我修復的。在大多數狀況下,它由外部系統實現,該系統會監視實例運行情況,並在較長時間內處於故障狀態時從新啓動它們。自我修復在大多數狀況下是很是有用的。可是在某些狀況下,持續地重啓應用程序可能會致使麻煩。 當您的應用程序因爲超負荷或其數據庫鏈接超時而沒法給出健康的運行情況時,這種狀況下的頻繁的重啓就可能就不太合適了。
對於這種特殊的場景(如丟失的數據庫鏈接),要實現知足它的高級自我修復的解決方案可能很棘手。在這種狀況下,您須要爲應用程序添加額外的邏輯來處理邊緣狀況,並讓外部系統知道實例不須要當即從新啓動。
因爲網絡問題和咱們系統的變化,服務常常會失敗。然而,因爲自我修復和負載均衡的保障,它們中的大多數中斷是臨時的,咱們應該找到一個解決方案,使咱們的服務在這些故障時服務仍就能夠工做。這就是故障轉移緩存的做用,它能夠幫助併爲咱們的應用程序在服務故障時提供必要的數據。
故障轉移緩存一般使用兩個不一樣的到期日期; 較短的時間告訴您在正常狀況下緩存可使用的過時時間,而較長的時間能夠在服務故障時緩存依舊可用的過時時間。
請務必說起,只有當服務使用過期的數據比沒有數據更好時,才能使用故障轉移緩存。
要設置緩存和故障轉移緩存,能夠在 HTTP 中使用標準響應頭。
例如,使用 max-age
屬性能夠指定資源被視爲有效的最大時間。使用 stale-if-error
屬性,您能夠明確在出現故障的狀況下,依舊能夠從緩存中獲取資源的最大時間。
現代的 CDN 和負載均衡器都提供各類緩存和故障轉移行爲,但您也能夠爲擁有標準可靠性解決方案的公司建立一個共享庫。
在某些狀況下,咱們沒法緩存數據,或者咱們想對其進行更改,可是咱們的操做最終都失敗了。對於此,咱們能夠重試咱們的操做,由於咱們能夠預期資源將在一段時間後恢復,或者咱們的負載均衡器將請求發送到了健康的實例上。
您應該當心地爲您的應用程序和客戶端添加劇試邏輯,由於大量的重試可能會使事情更糟,甚至阻止應用程序恢復,如當服務超載時,大量的重試只能使情況更糟。
在分佈式系統中,微服務系統重試能夠觸發多個其餘請求或重試,並啓動級聯效應。爲了最小化重試的影響,您應該限制它們的數量,並使用指數退避算法來持續增長重試之間的延遲,直到達到最大限制。
當客戶端(瀏覽器,其餘微服務等)發起重試,而且客戶端不知道在處理請求以前或以後操做失敗時,您應該爲你的應用程序作好冪等處理的準備。例如,當您重試購買操做時,您不該該再次向客戶收取費用。爲每一個交易使用惟一的冪等值鍵能夠幫助處理重試。
流量限制是在一段時間內定義特定客戶或應用程序能夠接收或處理多少個請求的技術。例如,經過流量限制,您能夠過濾掉形成流量峯值的客戶和服務,或者您能夠確保您的應用程序在自動縮放沒法知足時,依然不會超載。
您還能夠阻止較低優先級的流量,爲關鍵事務提供足夠的資源。
有一個不一樣類型的限流器,叫作併發請求限制器。當您有重要的端點,您不該該被調用超過指定的次數,而您仍然想要能提供服務時,這將是有用的。
負載降級的一系列使用,能夠確保老是有足夠的資源來提供關鍵交易。它爲高優先級請求保留一些資源,不容許低優先級的事務使用它們。負載降級開關是根據系統的總體狀態作出決定,而不是基於單個用戶的請求量大小。負載降級有助於您的系統恢復,由於當你有一個偶發事件時(
要了解有關限流器和負載降級的更多信息,我建議查看這篇Stripe的文章。
在微服務架構中,咱們想要作到讓咱們的服務具有快速失敗與相互獨立的能力。爲了在服務級別上進行故障隔離,咱們可使用艙壁模式。你能夠在本文的後面閱讀更多有關艙壁的內容。
咱們也但願咱們的組件可以快速失敗,由於咱們不但願對於有故障的服務,在請求超時後才斷開。沒有什麼比掛起的請求和無響應的 UI 更使人失望。這不只浪費資源,並且還會影響用戶體驗。咱們的服務在調用鏈中是相互調用的,因此在這些延遲累加以前,咱們應該特別注意防止掛起操做。
你想到的第一個想法是對每一個服務調用都設置明確的超時等級。這種方法的問題是,您不能知道真正合理的超時值是多少,由於網絡故障和其餘問題發生的某些狀況只會影響一兩次操做。在這種狀況下,若是隻有其中一些超時,您可能不想拒絕這些請求。
咱們能夠說,在微服務種經過使用超時來達到快速失敗的效果是一種反模式的,你應該避免使用它。取而代之,您能夠應用斷路器模式,依據操做的成功與失敗統計數據決定。
工業中使用艙壁將船舶劃分爲幾個部分,以便在船體破壞的狀況下,能夠將船舶各個部件密封起來。
艙壁的概念在軟件開發中能夠被應用在隔離資源上。
經過應用艙壁模式,咱們能夠保護有限的資源不被耗盡。例如,對於一個有鏈接數限制的數據庫實例來講,若是咱們有兩種鏈接它的操做,咱們採用能夠採用兩個鏈接池的方式進行鏈接,來代替僅採用一個共享鏈接池的方式。因爲這種客戶端與資源進行了隔離,超時或過分使用池的操做頁不會使其餘操做失敗。
泰坦尼克號沉沒的主要緣由之一是其艙壁設計失敗,水能夠經過上面的甲板倒在艙壁的頂部,致使整個船體淹沒。
爲了限制操做的持續時間,咱們可使用超時。超時能夠防止掛起操做並保持系統響應。然而,在微服務中使用靜態、精細的超時是一種反模式,由於咱們處於高度動態的環境中,幾乎不可能提出在每種狀況下都能正常工做的正確的時間限制。
替代這種靜態超時的手段是,咱們可使用斷路器來處理錯誤。斷路器以現實世界的電子元件命名,由於它們的做用是相同的。您能夠保護資源,並幫助他們使用斷路器進行恢復。它們在分佈式系統中很是有用,由於在分佈式系統中,重複故障可能致使雪球效應並使整個系統癱瘓。
當特定類型的錯誤在短期內屢次發生時,斷路器會被斷開。開路的斷路器能夠防止進一步的請求 – 就像咱們平時所說的電路跳閘同樣。斷路器一般在必定時間後關閉,在這期間能夠爲底層服務提供足夠的空間來恢復。
請記住,並非全部的錯誤都應該觸發斷路器。例如,您可能但願跳過客戶端問題,例如具備4xx響應代碼的請求,但不包括5xx服務器端故障。一些斷路器也具備半開狀態。在這種狀態下,服務發送第一個請求以檢查系統可用性,同時讓其餘請求失敗。若是這個第一個請求成功,它將使斷路器恢復到關閉狀態並使流量流動。不然,它保持打開。
您應該不斷測試您系統的常見問題,以確保您的服務能夠抵抗各類故障。您應常常測試故障,讓您的團隊具有故障處理的能力。
對於測試,您可使用外部服務來標識實例組,並隨機終止此組中的一個實例。這樣,您能夠準備單個實例故障,但您甚至能夠關閉整個區域來模擬雲提供商的故障。
最流行的測試解決方案之一是 Netflix 的 ChaosMonkey 彈性工具。
實施和運行可靠的服務並不容易。 您須要付出不少努力,同時公司也要有相應的財力投入。
可靠性有不少層次和方面,所以找到最適合您團隊的解決方案很重要。您應該使可靠性成爲您的業務決策流程中的一個因素,併爲其分配足夠的預算和時間。