我們調用的每個遠程服務最終都會失敗。無論它們多么可靠,這都是不可避免的。這些失敗可能來自多種因素。網絡問題,硬件問題,暫時不可用的服務,超出響應時間等。其中一些故障可能已經在短時間內自動解決,如果再次調用遠程服務,它將立即成功響應。我們稱這些錯誤為暫時錯誤。當我們遇到暫時性錯誤時,我們可以做一些事情。
最簡單的選擇是記錄錯誤并放棄。由于重試時最有可能解決暫時性錯誤,因此您可能會猜測這不是最明智的選擇。因此,正確的策略是重試失敗的操作。在沒有明確策略的情況下重試失敗的操作很可能會給遠程服務造成額外的負擔,因此可能會使情況變得最糟。
應用重試策略之前應回答的一些問題是:
客戶將如何確定錯誤是否是瞬態的?
客戶應多久重試一次?
客戶端應重試多長時間?
客戶什么時候應該放棄?
那么,什么時候重試?
您可以確定這是暫時性錯誤
如果遠程服務返回TransientErrorException,那就很好。但是,這并不總是可能的。在這些情況下,我們需要在解釋錯誤時保持機敏。
客戶端錯誤:這些是由客戶端本身引起的錯誤。例如格式錯誤的請求,導致沖突或執行過多的請求。在這種情況下,遠程服務將返回4xx錯誤。處理客戶端錯誤的唯一方法是通過人工干預來修復客戶端或請求自身。沒有必要重試這些請求。
服務器錯誤:這些是5xx錯誤,表明服務器端發生了問題。在這些情況下,重試通常是安全的,因為每個5xx錯誤都不是瞬時錯誤。
網絡錯誤:這些是由于網絡問題引起的錯誤。例如包丟失,路由器/交換機等硬件問題等。如果可以識別出這些,可以重試。
服務是冪等的
冪等意味著,在發出多個相同的請求時,其效果與發出單個請求的效果相同
根據HTTP規范的定義,GET,HEAD,PUT和DELETE是冪等操作。因此,除非遠程服務所有者建議,否則可以重試這些請求。另一方面,POST和PATCH不是冪等的,如果不應用冪等,則重試是不安全的,因為它可能會引起副作用,例如多次向客戶收費。
重試策略
可以用作重試機制的幾種策略。選擇正確的策略取決于用例。
操作失敗后,我們可以立即重試。這是我們可以實施的最簡單的重試策略。在第一次失敗的重試操作之后,最好放棄或回退更好的策略,因為連續重試會給遠程服務造成過多的負載。
操作失敗后,我們可以按固定的時間間隔重試。該策略為遠程服務提供了更多時間進行恢復。
這兩種策略對于與用戶進行交互的應用程序都非常有用,因為這些策略會重試失敗的操作,如果操作失敗,則很可能會放棄。因此,用戶不必等待很長時間。
如果您的服務/應用程序不直接與用戶交互和/或您有奢望等待更多(例如后臺操作),則應嘗試指數級退避。此策略基于后續重試之間的等待時間成倍增加。這是一項非常有用的技術,因為在給定的時間段內,它比以前的兩種策略都給遠程服務更多的時間來恢復并創建更少的負載。
那么,什么樣的指數回退策略是什么樣的呢?
這是一種簡單的指數退避策略算法的簡化偽代碼:
通過增加一些抖動來分配負載
最有可能存在多個客戶端實例,因此,如果這些客戶端發出的所有請求都在同一時間失敗,則我們不希望這些重試重疊。增加抖動將使負載分配更加均勻。使用jiter,我們的算法將是:
通過上述介紹,我們可以知道當遠程服務暫時性錯誤,并不是所有的錯誤都適用重試策略,這也是分情況而定的,更多精彩內容,請繼續關注中培偉業。