天天看點

重試模式-常用的架構設計原則

當應用程式嘗試連接配接到服務或網絡資源時,使應用程式能夠通過以透明方式重試失敗的操作來處理臨時故障。 這可以提高應用程式的穩定性。

上下文和問題

與在雲中運作的元素進行通信的應用程式必須能夠敏感地察覺到此環境中可能會出現的暫時性錯誤。 這類故障包括元件和服務瞬間斷開網絡連接配接、服務暫時不可用,或者當服務繁忙時出現逾時。

這些錯誤通常可以自己修複,如果在延遲合适的時間後重新執行觸發了錯誤的操作,該操作可能會成功。 例如,處理大量并發請求的資料庫服務可以實作限制政策,該政策會暫時拒絕任何後續請求,直到其工作負荷得以減輕。 嘗試通路該資料庫的應用程式可能無法連接配接,但如果它在延遲一段時間後再次嘗試,則可能會成功。

解決方案

在雲中,暫時性錯誤很常見,是以應當将應用程式設計為能夠優雅地以透明方式處理它們。 這可以盡量降低錯誤可能會給應用程式正在執行的業務任務帶來的影響。

如果應用程式在嘗試将請求發送到遠端服務時檢測到故障,則它可以使用以下政策來處理故障:

  • 取消。 如果錯誤表明故障不是暫時性的或者在重新執行的情況下不可能成功,則應用程式應當取消操作并報告異常。 例如,對于因為提供了無效的憑據而導緻的身份驗證失敗,無論嘗試多少次,身份驗證都不可能成功。
  • 重試。 如果所報告的具體錯誤不常見或極少見,則它可能是由不常見的情況(例如網絡包在傳輸過程中損壞)導緻的。 在這種情況下,應用程式可以立即再次重試失敗的請求,因為不大可能會重複出現同一故障并且請求可能會成功。
  • 延遲後重試。 如果錯誤是由更普遍的連接配接或繁忙故障之一引起的,則網絡或服務可能需要很短的一段時間來等待連接配接問題得以修複或積壓的工作得以清除。 應用程式應當等待合适的時間,然後重試請求。

對于更常見的暫時性故障,在選擇重試之間的時長時應當考慮使來自應用程式的多個執行個體的請求盡可能均勻地分布。 這可以降低繁忙的服務持續過載的可能性。 如果應用程式的許多執行個體由于重試請求而導緻某個服務持續過載,則該服務将需要更長的時間才能恢複。

如果請求仍然失敗,則應用程式可以等待并進行另一嘗試。 如果需要,可以在增大重試嘗試之間的延遲時間的情況下不斷重複此過程,直到已嘗試的請求數目達到某個最大數目。 可以采用遞增方式或指數方式增大延遲時間,具體取決于故障的類型和它在此時間段内被更正的可能性。

應用程式應當将通路遠端服務的所有嘗試包裝在代碼中并在代碼中實作與上面列出的政策之一比對的重試政策。 發送到不同服務的請求遵守不同的政策。 某些供應商提供了實作了重試政策的庫,應用程式可以在這些重試政策中指定最大重試次數、重試嘗試之間的間隔時間以及其他參數。

應用程式應當記錄錯誤和失敗操作的詳細資訊。 此資訊對操作員比較有用。 這就是,為了避免在後續重試嘗試成功的情況下使用警報的流處理操作員,最好是将早期失敗記錄為 資訊性條目 ,并且僅将最後一次重試嘗試失敗作為實際錯誤記錄。 

如果某個服務頻繁不可用或繁忙,通常是由于該服務已耗盡了其資源。 可以通過橫向擴充該服務來降低出現這些錯誤的頻率。 例如,如果某個資料庫服務持續過載,則對資料庫進行分區并将負載分布到多個伺服器中可能有助于解決問題。

問題和注意事項

在決定如何實作此模式時,應考慮以下幾點。

應當對重試政策進行調整以比對應用程式的業務要求和故障性質。 對于某些非關鍵操作,最好是快速失敗而不是重試多次并影響應用程式的吞吐量。 例如,在通路遠端服務的互動式 Web 應用程式中,最好是在重試較少次數後失敗并且重試嘗試之間的延遲時間應當很短,而且最好向使用者顯示合适的消息(例如“請稍後重試”)。 對于批處理應用程式,增加重試嘗試次數并且在嘗試之間采用呈指數級增長的延遲時間可能更為合适。

對于運作狀況已接近或處于其容量上限的繁忙服務,如果采用嘗試延遲時間間隔最小且嘗試次數較多的積極重試政策,則可能會進一步降低性能。 如果此重試政策不斷嘗試執行失敗的操作,則它還可能會影響應用程式的響應能力。

如果某個請求在進行大量的重試後失敗,則應用程式最好是阻止發往同一資源的後續請求并立即報告失敗。 當期限過期後,應用程式可以試探性地允許一個或多個請求通過以檢視它們是否成功。 有關此政策的詳細資訊,請參閱斷路器模式。

請考慮操作是否是幂等的。 如果是,則可以放心地進行重試。 否則,重試可能會導緻操作執行多次并産生意外的副作用。 例如,某個服務可以收到請求,成功處理該請求,但無法發送響應。 此時,重試邏輯可能會認為第一個請求沒有收到并重新發送請求。

對服務的請求可能會因各種原因而失敗并引發不同的異常,具體取決于故障性質。 某些異常表明故障可以快速解決,而另一些異常表明故障會持續較長時間。 根據異常類型為重試政策調整重試嘗試之間的時間間隔會起作用。

請考慮屬于事務一部分的操作将如何影響總體的事務一緻性。 請優調事務操作的重試政策以盡量提高成功幾率并降低撤消所有事務步驟的需求。

請確定針對各種故障狀況充分測試重試代碼。 請檢查并確定它不會嚴重影響應用程式的性能或可靠性、不會導緻服務和資源過載,不會導緻争用狀況或瓶頸。

隻有充分了解失敗操作的完整上下文後才應實作重試邏輯。 例如,如果某個任務包含的重試政策會調用也包含重試政策的另一任務,則這一層額外的重試可能會給處理增加很長的延遲。 更好的解決方案可能是将較低級别的任務配置為快速失敗并将失敗原因報告給調用它的任務。 然後,此較進階别的任務可以根據自己的政策處理失敗。

請務必記錄導緻重試的所有連接配接故障,以便可以查明應用程式、服務或資源的底層問題。

請調查服務或資源最有可能發生的錯誤以查明它們可能持續很長時間還是已處于末期。 如果可能持續很長時間,則最好将錯誤作為異常進行處理。 應用程式可以報告或記錄異常,然後嘗試通過調用備用服務(如果有)或通過提供降級的功能來繼續運作。 有關如何檢測和處理持續時間很長的錯誤的詳細資訊,請參閱斷路器模式。

何時使用此模式

當應用程式與遠端服務進行互動或者通路遠端資源時可能會遇到暫時性錯誤時,請使用此模式。 這些錯誤預計隻會短時存在,并且通過後續嘗試重複執行之前失敗的請求可能會成功。

在下列情況下,此模式可能不适用:

  • 當錯誤可能會持續很長時間時,因為此模式可能會影響應用程式的響應能力。 如果應用程式嘗試重複執行可能會失敗的請求,可能會浪費時間和資源。
  • 處理不是由于出現暫時性錯誤而導緻的故障,例如,由應用程式的業務邏輯中的錯誤導緻的内部異常。
  • 作為替代方法來解決系統中的可伸縮性問題。 如果應用程式遇到頻繁的繁忙錯誤,則這通常表明應當縱向擴充正在通路的服務或資源。

繼續閱讀