一文讀懂熔斷器和重試機制

導語:隨著微服務的流行,熔斷作為其中一項很重要的技術也廣為人知。當微服務的運行質量低於某個臨界值時,啟動熔斷機制,暫停微服務調用一段時間,以保障後端的微服務不會因為持續過負荷而宕機。本文作者介紹了熔斷的原理和機制,並用例子說明了熔斷如何使用。

今天,讓我們討論一下微服務架構的彈性伸縮。總的來說,各個服務之間可以通過同步或者異步的方式通訊。我們假定把一個大的單個系統拆分成若干小的模塊以便解偶服務。事實上,這樣可能更加難以管理內部服務之間的通訊。

這裡有兩個你們可能聽過的概念:熔斷器和重試機制。

熔斷器

一文读懂熔断器和重试机制

設想一個簡單的場景,其中用戶的請求調用服務A,隨後調用另一個服務。我們可以把B稱作A的下游服務。服務B前面有負載均衡器。

後端服務可能因為各種原因出問題。例如:數據庫慢查詢,網絡波動,或者內存爭用。在這個情況下,如果服務A超時或者報錯,用戶很可能會重試。在如此混亂的情況下我們可以做什麼來保護下游服務呢?

一文读懂熔断器和重试机制

熔斷器為資源和失敗率提供更多的控制。斷路器被設計為在不等待TCP連接超時的情況下快速而優雅地處理錯誤。這種快速失敗機制將保護下游服務。這個機制最重要的部分是熔斷器能夠快速對下游服務作出一些響應。線程池不會因為慢請求而阻塞,沒有超時,而且也可能會給終端用戶更有意義的返回數據。熔斷器也給了下游服務足夠的時間恢復正常。完全避免報錯是很困難的,但是減少錯誤的影響完全可行。

一文读懂熔断器和重试机制

通過使用hystrix熔斷器,我們可以在上游服務中增加降級行為。例如,服務B可以訪問副本服務或緩存,而不是調用服務C。引入這種方法需要整合測試,因為我們可能無法在好的鏈路上模擬這種方式。

狀態

一文读懂熔断器和重试机制

在熔斷器裡面有3種主要的狀態:

  • 關閉:讓請求通過的默認狀態。如果請求成功/失敗但低於閾值,則狀態保持不變。可能出現的錯誤是超過最大併發數和超時錯誤。

  • 打開:當熔斷器打開的時候,所有的請求都會被標記為失敗;這是故障快速失敗機制,而不需要等待超時時間完成。

  • 半開:定期的嘗試發起請求來確認系統是否恢復。如果恢復了,熔斷器將轉為關閉狀態或者保持打開。

理論上的熔斷器

這裡有5個控制熔斷設置的主要參數。

一文读懂熔断器和重试机制

閥值可以從兩個服務的SLA中得到。當測試服務與其它依賴的穩定性時,這些值應該合理設置。

一個好的熔斷器命名應該指明相應的服務連接報錯了。實際上,你可能有許多API endpoint在同一個服務。所以針對每個API endpoint需要配置單獨的熔斷器。

生產環境的熔斷器

一個熔斷器通常被部署在多個節點。即使熔斷器提供一個快速報錯機制,我們依然需要確認備用的降級邏輯是生效的。因為我們覺得這是一個小概率事件而不測試對應的降級策略是冒險的行為。在最簡單的運行中,我們也需要確定閥值是合理的。從我的個人經歷來說,在日誌裡面打印出配置參數將讓調試更加簡單。

Demo

這個樣例代碼使用hystrix-go庫,這是golang的hystrix Netflix庫實現。

一文读懂熔断器和重试机制
一文读懂熔断器和重试机制一文读懂熔断器和重试机制

運行這個測試,你將看到2次的返回結果不同。

重試機制

對上面的熔斷器模型,如果B服務減小它的實例數量,將發生什麼?許多A發起的請求可能遇到5XX報錯。這將觸發熔斷器的失敗報警。這就是為什麼我們需要重試以避免間歇性網絡抽風。

簡單的重試代碼:

一文读懂熔断器和重试机制

重試模式

為了實現樂觀的併發控制,我們可以編排不同的服務在不同的時間重試。立即重試可能不太合適,因為這樣會對依賴服務的突然大量的請求。增加暫停時間將有助於緩解這種情景。也可以讓暫停時間在一定範圍內隨機(或者說在等待階段抖動一下)。

讓我們想一下下面這個算法:

  • 指數: 基數* 2^嘗試次數

  • 全抖動: 休眠時間 = rand(0 , 基數* 2^嘗試次數)

  • 等抖動: 臨時 = 基數 * 2^嘗試次數; 休眠時間= 臨時/2+rand(0 , 臨時/2)

  • 不相關抖動: 休眠時間= rand(基數, 休眠時間\*3);

一文读懂熔断器和重试机制

客戶端數量與負載總量和完成時間之間存在相關性。要確定最適合系統的方法,有必要在客戶端數量增加時進行基準測試。詳細的實驗可以在本文中找到。我的建議是在去抖動和全抖動之間。

兩種工具的結合

一文读懂熔断器和重试机制

斷路器通常用於無狀態在線交易系統,尤其是在關鍵節點上。重試應該用於調度不受超時約束的任務或節點。我們可以考慮同時使用兩者。在大型系統中,service mesh將是一種更好地協調大規模異構系統的理想架構。

參考鏈接:

1. https://github.com/afex/hystrix-go/

2. https://github.com/eapache/go-resiliency

3. https://github.com/Netflix/Hystrix/wiki

4. https://www.awsarchitectureblog.com/2015/03/backoff.html

5. https://dzone.com/articles/go-microservices-part-11-hystrix-and-resilience

原文地址:

https://medium.com/@trongdan_tran/circuit-breaker-and-retry-64830e71d0f6

本文作者Dan Tran,由朱毅堃翻譯。轉載本文請註明出處,歡迎更多小夥伴加入翻譯及投稿文章的行列,詳情請戳公眾號菜單「聯繫我們」。

參考閱讀:

高可用架構

改變互聯網的構建方式

長按二維碼 關注「高可用架構」公眾號


分享到:


相關文章: