Micronaut 重試 Advice

2023-03-02 14:44 更新

在分布式系統(tǒng)和微服務(wù)環(huán)境中,失敗是您必須計劃的事情,并且通常希望在失敗時嘗試重試操作。如果第一次你沒有成功再試一次!

考慮到這一點,Micronaut 包含一個 Retryable 注釋。

簡單重試

最簡單的重試形式就是將 @Retryable 注釋添加到類型或方法。 @Retryable 的默認行為是重試三次,每次重試之間的指數(shù)延遲為一秒。 (第一次嘗試延遲 1 秒,第二次嘗試延遲 2 秒,第三次嘗試延遲 3 秒)。

例如:

簡單重試示例

 Java Groovy  Kotlin 
@Retryable
public List<Book> listBooks() {
    // ...
@Retryable
List<Book> listBooks() {
    // ...
@Retryable
open fun listBooks(): List<Book> {
    // ...

對于上面的示例,如果 listBooks() 方法拋出 RuntimeException,則會重試直到達到最大嘗試次數(shù)。

@Retryable 注釋的乘數(shù)值可用于配置用于計算重試之間延遲的乘數(shù),從而允許指數(shù)重試支持。

要自定義重試行為,請設(shè)置 attempts 和 delay 成員,例如配置五次嘗試和兩秒延遲:

設(shè)置重試次數(shù)

 Java Groovy  Kotlin 
@Retryable(attempts = "5",
           delay = "2s")
public Book findBook(String title) {
    // ...
@Retryable(attempts = "5",
           delay = "2s")
Book findBook(String title) {
    // ...
@Retryable(attempts = "5",
           delay = "2s")
open fun findBook(title: String): Book {
    // ...

請注意嘗試和延遲是如何定義為字符串的。這是為了通過注釋元數(shù)據(jù)支持可配置性。例如,您可以允許使用屬性占位符解析來配置重試策略:

通過配置設(shè)置重試

 Java Groovy  Kotlin 
@Retryable(attempts = "${book.retry.attempts:3}",
           delay = "${book.retry.delay:1s}")
public Book getBook(String title) {
    // ...
@Retryable(attempts = '${book.retry.attempts:3}',
           delay = '${book.retry.delay:1s}')
Book getBook(String title) {
    // ...
@Retryable(attempts = "\${book.retry.attempts:3}",
           delay = "\${book.retry.delay:1s}")
open fun getBook(title: String): Book {
    // ...

有了上面的內(nèi)容,如果在配置中指定了 book.retry.attempts,它就會通過注釋元數(shù)據(jù)綁定到 @Retryable 注釋的 attempts 成員的值。

Reactive Retry(反應(yīng)性重試)

@Retryable 通知也可以應(yīng)用于返回反應(yīng)類型的方法,例如 Publisher(Project Reactor 的 Flux 或 RxJava 的 Flowable)。例如:

將重試策略應(yīng)用于反應(yīng)類型

 Java Groovy  Kotlin 
@Retryable
public Publisher<Book> streamBooks() {
    // ...
@Retryable
Flux<Book> streamBooks() {
    // ...
@Retryable
open fun streamBooks(): Flux<Book> {
    // ...

在這種情況下,@Retryable 建議將重試策略應(yīng)用于反應(yīng)類型。

Circuit Breaker(斷路器)

重試在微服務(wù)環(huán)境中很有用,但在某些情況下,過多的重試會使系統(tǒng)不堪重負,因為客戶端會反復(fù)重新嘗試失敗的操作。

斷路器模式旨在通過允許一定數(shù)量的失敗請求然后打開一個保持打開狀態(tài)一段時間的電路來解決此問題,然后再允許進行額外的重試嘗試。

CircuitBreaker 注釋是 @Retryable 注釋的變體,它支持一個 reset 成員,該成員指示電路在重置之前應(yīng)保持打開狀態(tài)的時間(默認值為 20 秒)。

應(yīng)用斷路器建議

 Java Groovy  Kotlin 
@CircuitBreaker(reset = "30s")
public List<Book> findBooks() {
    // ...
@CircuitBreaker(reset = "30s")
List<Book> findBooks() {
    // ...
@CircuitBreaker(reset = "30s")
open fun findBooks(): List<Book> {
    // ...

上面的示例重試 findBooks 方法 3 次,然后打開電路 30 秒,重新拋出原始異常并防止?jié)撛诘南掠瘟髁浚ɡ?nbsp;HTTP 請求和 I/O 操作)淹沒系統(tǒng)。

Factory Bean Retry

當(dāng) @Retryable 應(yīng)用于 bean 工廠方法時,它的行為就像注釋被放置在返回的類型上一樣。當(dāng)調(diào)用返回對象上的方法時,重試行為適用。請注意,bean 工廠方法本身不會重試。如果您希望重試創(chuàng)建 bean 的功能,則應(yīng)將其委托給另一個應(yīng)用了 @Retryable 注釋的單例。

例如:

@Factory (1)
public class Neo4jDriverFactory {
    ...
    @Retryable(ServiceUnavailableException.class) (2)
    @Bean(preDestroy = "close")
    public Driver buildDriver() {
        ...
    }
}
  1. 創(chuàng)建了一個工廠 bean,它定義了創(chuàng)建 bean 的方法

  2. @Retryable 注釋用于捕獲從驅(qū)動程序上執(zhí)行的方法拋出的異常。

重試事件

您可以將 RetryEventListener 實例注冊為 bean,以偵聽每次重試操作時發(fā)布的 RetryEvent 事件。

此外,您可以為 CircuitOpenEvent 注冊事件偵聽器,以便在斷路器電路打開時收到通知,或者在電路關(guān)閉時收到 CircuitClosedEvent 的通知。


以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號