国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

Spring 指南(spring-retry)

xiaotianyi / 1834人閱讀

摘要:包含一些狀態來決定是重試還是中止,但是這個狀態位于堆棧上,不需要將它存儲在全局的任何位置,因此我們將此稱為無狀態重試。將拋出原始異常,除非在有狀態的情況下,當沒有可用的恢復,在這種情況下,它將拋出。

spring-retry

該項目為Spring應用程序提供聲明式重試支持,它用于Spring Batch、Spring Integration、Apache Hadoop的Spring(以及其他),命令式重試也支持顯式使用。

入門 聲明式示例
@Configuration
@EnableRetry
public class Application {

    @Bean
    public Service service() {
        return new Service();
    }

}

@Service
class Service {
    @Retryable(RemoteAccessException.class)
    public void service() {
        // ... do something
    }
    @Recover
    public void recover(RemoteAccessException e) {
       // ... panic
    }
}

調用service方法,如果它由于RemoteAccessException失敗,那么它將重試(默認情況下最多三次),如果繼續失敗,則執行recover方法,@Retryable注解屬性中有各種選項,用于包含和排除異常類型、限制重試次數和回退策略。

使用上面顯示的@Retryable注解應用重試處理的聲明式方法對AOP類有一個額外的運行時依賴,有關如何解決項目中的這種依賴關系的詳細信息,請參閱下面的“重試代理的Java配置”部分。

命令式示例
RetryTemplate template = RetryTemplate.builder()
                .maxAttempts(3)
                .fixedBackoff(1000)
                .retryOn(RemoteAccessException.class)
                .build();

template.execute(ctx -> {
    // ... do something
});

舊版本:參見RetryTemplate部分中的示例。

構建

要求Java 1.7和Maven 3.0.5(或更高)。

$ mvn install
特性和API RetryTemplate

為了使處理更健壯、更不容易失敗,有時自動重試失敗的操作會有所幫助,以防它在隨后的嘗試中可能成功,易受這種處理影響的錯誤本質上是暫時的。例如,對web服務或RMI服務的遠程調用由于網絡故障或數據庫更新中的DeadLockLoserException而失敗,可能在短時間的等待后自行解決,要自動化這些操作的重試,Spring Retry具有RetryOperations策略,RetryOperations接口看起來是這樣的:

public interface RetryOperations {

     T execute(RetryCallback retryCallback) throws Exception;

     T execute(RetryCallback retryCallback, RecoveryCallback recoveryCallback)
        throws Exception;

     T execute(RetryCallback retryCallback, RetryState retryState)
        throws Exception, ExhaustedRetryException;

     T execute(RetryCallback retryCallback, RecoveryCallback recoveryCallback,
        RetryState retryState) throws Exception;

}

基本回調是一個簡單的接口,允許你插入一些要重試的業務邏輯:

public interface RetryCallback {

    T doWithRetry(RetryContext context) throws Throwable;

}

執行回調,如果它失敗(通過拋出Exception),將重試它,直到成功或實現決定中止為止。RetryOperations接口中有許多重載的execute方法,它們處理各種用例,以便在所有重試嘗試都耗盡時進行恢復,還有重試狀態,這允許客戶端和實現在調用之間存儲信息(稍后將詳細介紹)。

RetryOperations最簡單的通用實現是RetryTemplate,它可以這樣用:

RetryTemplate template = new RetryTemplate();

TimeoutRetryPolicy policy = new TimeoutRetryPolicy();
policy.setTimeout(30000L);

template.setRetryPolicy(policy);

Foo result = template.execute(new RetryCallback() {

    public Foo doWithRetry(RetryContext context) {
        // Do stuff that might fail, e.g. webservice operation
        return result;
    }

});

在本例中,我們執行一個web服務調用并將結果返回給用戶,如果該調用失敗,則重試該調用,直到達到超時為止。

從1.3版開始,RetryTemplate的流暢配置也可用:

RetryTemplate.builder()
      .maxAttempts(10)
      .exponentialBackoff(100, 2, 10000)
      .retryOn(IOException.class)
      .traversingCauses()
      .build();
 
RetryTemplate.builder()
      .fixedBackoff(10)
      .withinMillis(3000)
      .build();
 
RetryTemplate.builder()
      .infiniteRetry()
      .retryOn(IOException.class)
      .uniformRandomBackoff(1000, 3000)
      .build();
RetryContext

RetryCallback的方法參數是一個RetryContext,許多回調將簡單地忽略上下文,但是如果需要,它可以作為一個屬性包來存儲迭代期間的數據。

如果同一個線程中正在進行嵌套重試,則RetryContext將具有父上下文,父上下文有時對于存儲需要在執行的調用之間共享的數據很有用。

RecoveryCallback

當重試耗盡時,RetryOperations可以將控制權傳遞給另一個回調RecoveryCallback,要使用此功能,客戶端只需將回調函數一起傳遞給相同的方法,例如:

Foo foo = template.execute(new RetryCallback() {
    public Foo doWithRetry(RetryContext context) {
        // business logic here
    },
  new RecoveryCallback() {
    Foo recover(RetryContext context) throws Exception {
          // recover logic here
    }
});

如果在模板決定中止之前業務邏輯沒有成功,那么客戶端就有機會通過恢復回調執行一些替代處理。

無狀態重試

在最簡單的情況下,重試只是一個while循環,RetryTemplate可以一直嘗試,直到成功或失敗。RetryContext包含一些狀態來決定是重試還是中止,但是這個狀態位于堆棧上,不需要將它存儲在全局的任何位置,因此我們將此稱為無狀態重試。無狀態重試和有狀態重試之間的區別包含在RetryPolicy的實現中(RetryTemplate可以同時處理這兩種情況),在無狀態重試中,回調總是在重試失敗時在同一個線程中執行。

有狀態重試

如果失敗導致事務性資源無效,則需要特別考慮,這并不適用于簡單的遠程調用,因為(通常)沒有事務資源,但有時確實適用于數據庫更新,尤其是在使用Hibernate時。在這種情況下,只有立即重新拋出調用失敗的異常才有意義,以便事務可以回滾并啟動一個新的有效的事務。

在這些情況下,無狀態重試是不夠的,因為重新拋出和回滾必然會離開RetryOperations.execute()方法,并可能丟失堆棧上的上下文。為了避免丟失它,我們必須引入一種存儲策略,將它從堆棧中取出并(至少)放入堆存儲中,為此,Spring Retry提供了一種存儲策略RetryContextCache,可以將其注入RetryTemplateRetryContextCache的默認實現在內存中,使用一個簡單的Map,它有一個嚴格執行的最大容量,以避免內存泄漏,但它沒有任何高級緩存功能,如生存時間。如果需要,應該考慮注入具有這些特性的Map,在集群環境中對多個進程的高級使用可能還會考慮使用某種集群緩存實現RetryContextCache(不過,即使在集群環境中,這也可能是多余的)。

RetryOperations的部分職責是在失敗的操作在新執行中返回時識別它們(通常封裝在新事務中),為了促進這一點,Spring Retry提供了RetryState抽象,這與RetryOperations中的特殊execute方法一起工作。

識別失敗操作的方法是跨重試的多個調用標識狀態,要標識狀態,用戶可以提供RetryState對象,該對象負責返回標識該項的唯一鍵,標識符用作RetryContextCache中的鍵。

RetryState返回的鍵中實現Object.equals()Object.hashCode()要非常小心,最好的建議是使用業務鍵來標識項,對于JMS消息,可以使用消息ID。

當重試耗盡時,還可以選擇以另一種方式處理失敗的項,而不是調用RetryCallback(現在假定很可能會失敗),就像在無狀態的情況下一樣,這個選項是由RecoveryCallback提供的,它可以通過將其傳遞給RetryOperationsexecute方法來提供。

重試或不重試的決定實際上委托給了一個常規的RetryPolicy,因此可以在那里注入對限制和超時的常見關注(參見下面)。

重試策略

RetryTemplate中,execute方法中重試或失敗的決定由RetryPolicy決定,RetryPolicy也是RetryContext的工廠。RetryTemplate有責任使用當前策略創建RetryContext,并在每次嘗試時將其傳遞給RetryCallback。回調失敗后,RetryTemplate必須調用RetryPolicy來要求它更新狀態(該狀態將存儲在RetryContext中),然后它詢問策略是否可以進行另一次嘗試。如果無法進行另一次嘗試(例如達到限制或檢測到超時),則策略還負責標識耗盡狀態,但不負責處理異常。RetryTemplate將拋出原始異常,除非在有狀態的情況下,當沒有可用的恢復,在這種情況下,它將拋出RetryExhaustedException。你還可以在RetryTemplate中設置一個標志,讓它無條件地從回調(即從用戶代碼)拋出原始異常。

失敗本質上要么是可重試的,要么是不可重試的 — 如果總是要從業務邏輯中拋出相同的異常,那么重試是沒有幫助的。所以不要在所有異常類型上重試 — 試著只關注那些你希望可以重試的異常。更積極地重試通常不會對業務邏輯造成損害,但這是浪費,因為如果失敗是確定的,那么重試一些預先知道是致命的東西就會花費時間。

Spring Retry提供了一些無狀態RetryPolicy的簡單通用實現,例如SimpleRetryPolicy和上面示例中使用的TimeoutRetryPolicy

SimpleRetryPolicy只允許對指定的異常類型列表中的任何一種進行重試,最多可以重試固定次數:

// Set the max attempts including the initial attempt before retrying
// and retry on all exceptions (this is the default):
SimpleRetryPolicy policy = new SimpleRetryPolicy(5, Collections.singletonMap(Exception.class, true));

// Use the policy...
RetryTemplate template = new RetryTemplate();
template.setRetryPolicy(policy);
template.execute(new RetryCallback() {
    public Foo doWithRetry(RetryContext context) {
        // business logic here
    }
});

還有一個更靈活的實現稱為ExceptionClassifierRetryPolicy,它允許用戶通過ExceptionClassifier抽象為任意一組異常類型配置不同的重試行為。策略的工作原理是調用分類器將異常轉換為委托RetryPolicy,例如,通過將一種異常類型映射到另一種策略,可以在失敗之前重試更多次。

用戶可能需要實現自己的重試策略來進行更定制的決策,例如,如果有一個眾所周知的、特定于解決方案的異常分類,則將其分為可重試和不可重試。

回退策略

在短暫故障之后重試時,在重試之前稍作等待通常會有所幫助,因為通常故障是由某些問題引起的,而這些問題只能通過等待來解決,如果RetryCallback失敗,RetryTemplate可以根據適當的BackoffPolicy暫停執行。

public interface BackoffPolicy {

    BackOffContext start(RetryContext context);

    void backOff(BackOffContext backOffContext)
        throws BackOffInterruptedException;

}

回退策略可以自由地以其選擇的任何方式實現回退,Spring Retry開箱即用提供的策略都使用Thread.sleep()。一個常見的用例是用指數級增長的等待時間來回退,以避免兩次重試進入鎖步,兩次都失敗 — 這是從以太網中學到的教訓。為此,Spring Retry提供了ExponentialBackoffPolicy,還有一些隨機版本的延遲策略,對于避免在復雜系統中的相關故障之間產生共振非常有用。

監聽器

對于跨多個不同重試的橫切關注點,能夠接收額外的回調通常是有用的,為此,Spring Retry提供了RetryListener接口,RetryTemplate允許用戶注冊RetryListeners,在迭代期間,他們將使用RetryContext獲得回調,并在可用的地方使用Throwable

接口是這樣的:

public interface RetryListener {

    void open(RetryContext context, RetryCallback callback);

    void onError(RetryContext context, RetryCallback callback, Throwable e);

    void close(RetryContext context, RetryCallback callback, Throwable e);
}

在最簡單的情況下,openclose回調出現在整個重試之前和之后,onError應用于各個RetryCallback調用,close方法也可能接收到一個Throwable,如果出現錯誤,則是RetryCallback拋出的最后一個錯誤。

注意,當有多個監聽器時,它們位于列表中,因此有一個順序,在這種情況下,open將以相同的順序調用,而onErrorclose將以相反的順序調用。

用于反射方法調用的監聽器

當處理用@Retryable注解的方法或用Spring AOP攔截的方法時,spring-retry提供了在RetryListener實現中詳細檢查方法調用的可能性。

當需要監視某個方法調用被重試的頻率并使用詳細的標記信息(例如:類名、方法名,甚至在某些特殊情況下的參數值)公開它時,這種場景可能特別有用。

template.registerListener(new MethodInvocationRetryListenerSupport() {
      @Override
      protected  void doClose(RetryContext context,
          MethodInvocationRetryCallback callback, Throwable throwable) {
        monitoringTags.put(labelTagName, callback.getLabel());
        Method method = callback.getInvocation()
            .getMethod();
        monitoringTags.put(classTagName,
            method.getDeclaringClass().getSimpleName());
        monitoringTags.put(methodTagName, method.getName());

        // register a monitoring counter with appropriate tags
        // ...
      }
    });
聲明式重試

有時候,有些業務處理你知道每次發生時都要重試,這方面的經典示例是遠程服務調用,Spring Retry提供了一個AOP攔截器,它將方法調用封裝在RetryOperations中正是出于這個目的。RetryOperationsInterceptor執行攔截方法,并根據所提供的RetryTemplate中的RetryPolicy在失敗時重試。

用于重試代理的Java配置

@EnableRetry注解添加到你的@Configuration類之一,并在要重試的方法(或所有方法的類型級別)上使用@Retryable,你還可以指定任意數量的重試監聽器,例如:

@Configuration
@EnableRetry
public class Application {

    @Bean
    public Service service() {
        return new Service();
    }
    
    @Bean public RetryListener retryListener1() {
        return new RetryListener() {...}
    }
    
    @Bean public RetryListener retryListener2() {
        return new RetryListener() {...}
    }

}

@Service
class Service {
    @Retryable(RemoteAccessException.class)
    public service() {
        // ... do something
    }
}

@Retryable的屬性可以用來控制RetryPolicyBackoffPolicy,例如:

@Service
class Service {
    @Retryable(maxAttempts=12, backoff=@Backoff(delay=100, maxDelay=500))
    public service() {
        // ... do something
    }
}

100500毫秒之間進行隨機回退,最多嘗試12次,還有一個stateful屬性(默認為false)來控制重試是否有狀態,要使用有狀態重試,攔截方法必須有參數,因為它們用于構造狀態的緩存鍵。

@EnableRetry注解還查找類型為Sleeperbean,以及RetryTemplate和攔截器中用于控制運行時重試行為的其他策略。

@EnableRetry注解為@Retryable bean創建代理,代理(應用程序中的bean實例)中添加了Retryable接口,這純粹是一個標記接口,但對于希望應用重試建議的其他工具可能很有用(如果bean已經實現了Retryable,那么它們通常不需要麻煩)。

可以提供恢復方法,以便在重試耗盡時采用另一種代碼路徑,方法應該與@Retryable在同一個類中聲明,并標記為@Recover,返回類型必須匹配@Retryable方法。恢復方法的參數可以有選擇地包括拋出的異常,也可以有選擇地包括傳遞給原始retryable方法的參數(或者它們的部分列表,只要沒有一個被省略),例如:

@Service
class Service {
    @Retryable(RemoteAccessException.class)
    public void service(String str1, String str2) {
        // ... do something
    }
    @Recover
    public void recover(RemoteAccessException e, String str1, String str2) {
       // ... error handling making use of original args if required
    }
}

1.2版引入了對某些屬性使用表達式的功能:

@Retryable(exceptionExpression="message.contains("this can be retried")")
public void service1() {
  ...
}

@Retryable(exceptionExpression="message.contains("this can be retried")")
public void service2() {
  ...
}

@Retryable(exceptionExpression="@exceptionChecker.shouldRetry(#root)",
    maxAttemptsExpression = "#{@integerFiveBean}",
  backoff = @Backoff(delayExpression = "#{1}", maxDelayExpression = "#{5}", multiplierExpression = "#{1.1}"))
public void service3() {
  ...
}

Spring Retry 1.2.5,對于exceptionExpression,不推薦使用模板表達式(#{...}),而支持簡單表達式字符串(message.contains("this can be retried"))。

表達式可以包含屬性占位符,比如#{${max.delay}}#{@exceptionChecker.${retry.method}(#root)}

exceptionExpression作為#root對象對拋出的異常求值。

maxAttemptsExpression@BackOff表達式屬性在初始化期間只計算一次,沒有用于計算的根對象,但是它們可以在上下文中引用其他bean

額外依賴項

使用上面顯示的@Retryable注解應用重試處理的聲明式方法對AOP類有額外的運行時依賴性,需要在項目中聲明這些類,如果你的應用程序是使用Spring Boot實現的,那么最好使用AOP的Spring Boot starter解決這個依賴關系,例如,對于Gradle,在build.gradle中添加以下行:

runtime("org.springframework.boot:spring-boot-starter-aop")

對于非Boot應用程序,聲明運行時依賴于AspectJ的aspectjweaver模塊的最新版本,例如,對于Gradle,在build.gradle中添加以下行:

runtime("org.aspectj:aspectjweaver:1.8.13")
XML配置

下面是一個使用Spring AOP來重復對一個名為remoteCall的方法的服務調用的聲明式迭代的例子(有關如何配置AOP攔截器的更多細節,請參閱Spring用戶指南):


    
    


上面的示例在攔截器中使用默認的RetryTemplate,要更改策略或監聽器,只需要將RetryTemplate實例注入攔截器。

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/75697.html

相關文章

  • spring retry, guava retrying 的整合-sisyphus java 重試框

    摘要:特性支持過程式編程基于字節碼的代理重試基于注解的重試,允許自定義注解無縫接入接口與注解的統一解決與中的不足之處設計目的綜合了和的優勢。基于字節碼實現的代理重試,可以不依賴。提供基于代碼模式字節碼增強實現的方式。 Sisyphus 支持過程式編程和注解編程的 java 重試框架。 特性 支持 fluent 過程式編程 基于字節碼的代理重試 基于注解的重試,允許自定義注解 無縫接入 sp...

    宋華 評論0 收藏0
  • Spring 指南(目錄)

    摘要:指南無論你正在構建什么,這些指南都旨在讓你盡快提高工作效率使用團隊推薦的最新項目版本和技術。使用進行消息傳遞了解如何將用作消息代理。安全架構的主題指南,這些位如何組合以及它們如何與交互。使用的主題指南以及如何為應用程序創建容器鏡像。 Spring 指南 無論你正在構建什么,這些指南都旨在讓你盡快提高工作效率 — 使用Spring團隊推薦的最新Spring項目版本和技術。 入門指南 這些...

    only_do 評論0 收藏0
  • Spring Cloud 配置中心客戶端讀取配置

    摘要:微服務連接配置中心來實現外部配置的讀取。引入依賴配置中心客戶端的依賴。增加啟動類添加配置在中添加如下配置,必須是,中不行。配置文件參考如下配置讀取配置使用就能讀取配置中心的配置,當然也可以通過其他方式獲取中的配置,參考之前系列文章。 微服務連接配置中心來實現外部配置的讀取。 引入依賴 org.springframework.cloud spr...

    endiat 評論0 收藏0
  • Spring Cloud Zuul的重試配置

    摘要:模塊本身就包含了對于和的依賴,當我們使用通過和的組合來配置路由的時候,可以通過和的配置調整路由請求的各種時間超時機制。 Spring Cloud Zuul模塊本身就包含了對于hystrix和ribbon的依賴,當我們使用zuul通過path和serviceId的組合來配置路由的時候,可以通過hystrix和ribbon的配置調整路由請求的各種時間超時機制。 1 ribbon配置舉例配置...

    TerryCai 評論0 收藏0
  • RestTemplate集成Ribbbon

    摘要:的類圖如下主要根據創建擴展了,創建攔截的,這里會設置攔截器,這是集成的核心,當發起請求調用的時候,會先經過攔截器,然后才真正發起請求。和是配合使用的,最大重試次數是針對每一個的,如果設置,這樣觸發最大重試次數就是次。 上一篇文章我們分析了ribbon的核心原理,接下來我們來看看springcloud是如何集成ribbon的,不同的springcloud的組件(feign,zuul,Re...

    wall2flower 評論0 收藏0

發表評論

0條評論

最新活動
閱讀需要支付1元查看
<