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