歡迎光臨
每天分享高質量文章

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

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


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


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


熔斷器


設想一個簡單的場景,其中使用者的請求呼叫服務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,由朱毅堃翻譯。轉載本文請註明出處,歡迎更多小夥伴加入翻譯及投稿文章的行列,詳情請戳公眾號選單「聯絡我們」。


參考閱讀:



技術原創及架構實踐文章,歡迎透過公眾號選單「聯絡我們」進行投稿。轉載請註明來自高可用架構「ArchNotes」微信公眾號及包含以下二維碼。


高可用架構

改變網際網路的構建方式


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

贊(0)

分享創造快樂