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

資訊專欄INFORMATION COLUMN

Spring 指南(spring-retry)

xiaotianyi / 1846人閱讀

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

spring-retry

該項目為Spring應(yīng)用程序提供聲明式重試支持,它用于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
    }
}

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

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

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

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

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

構(gòu)建

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

$ mvn install
特性和API RetryTemplate

為了使處理更健壯、更不容易失敗,有時自動重試失敗的操作會有所幫助,以防它在隨后的嘗試中可能成功,易受這種處理影響的錯誤本質(zhì)上是暫時的。例如,對web服務(wù)或RMI服務(wù)的遠(yuǎn)程調(diào)用由于網(wǎng)絡(luò)故障或數(shù)據(jù)庫更新中的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;

}

基本回調(diào)是一個簡單的接口,允許你插入一些要重試的業(yè)務(wù)邏輯:

public interface RetryCallback {

    T doWithRetry(RetryContext context) throws Throwable;

}

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

RetryOperations最簡單的通用實(shí)現(xiàn)是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;
    }

});

在本例中,我們執(zhí)行一個web服務(wù)調(diào)用并將結(jié)果返回給用戶,如果該調(diào)用失敗,則重試該調(diào)用,直到達(dá)到超時為止。

從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的方法參數(shù)是一個RetryContext,許多回調(diào)將簡單地忽略上下文,但是如果需要,它可以作為一個屬性包來存儲迭代期間的數(shù)據(jù)。

如果同一個線程中正在進(jìn)行嵌套重試,則RetryContext將具有父上下文,父上下文有時對于存儲需要在執(zhí)行的調(diào)用之間共享的數(shù)據(jù)很有用。

RecoveryCallback

當(dāng)重試耗盡時,RetryOperations可以將控制權(quán)傳遞給另一個回調(diào)RecoveryCallback,要使用此功能,客戶端只需將回調(diào)函數(shù)一起傳遞給相同的方法,例如:

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
    }
});

如果在模板決定中止之前業(yè)務(wù)邏輯沒有成功,那么客戶端就有機(jī)會通過恢復(fù)回調(diào)執(zhí)行一些替代處理。

無狀態(tài)重試

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

有狀態(tài)重試

如果失敗導(dǎo)致事務(wù)性資源無效,則需要特別考慮,這并不適用于簡單的遠(yuǎn)程調(diào)用,因?yàn)椋ㄍǔ#]有事務(wù)資源,但有時確實(shí)適用于數(shù)據(jù)庫更新,尤其是在使用Hibernate時。在這種情況下,只有立即重新拋出調(diào)用失敗的異常才有意義,以便事務(wù)可以回滾并啟動一個新的有效的事務(wù)。

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

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

識別失敗操作的方法是跨重試的多個調(diào)用標(biāo)識狀態(tài),要標(biāo)識狀態(tài),用戶可以提供RetryState對象,該對象負(fù)責(zé)返回標(biāo)識該項的唯一鍵,標(biāo)識符用作RetryContextCache中的鍵。

RetryState返回的鍵中實(shí)現(xiàn)Object.equals()Object.hashCode()要非常小心,最好的建議是使用業(yè)務(wù)鍵來標(biāo)識項,對于JMS消息,可以使用消息ID。

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

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

重試策略

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

失敗本質(zhì)上要么是可重試的,要么是不可重試的 — 如果總是要從業(yè)務(wù)邏輯中拋出相同的異常,那么重試是沒有幫助的。所以不要在所有異常類型上重試 — 試著只關(guān)注那些你希望可以重試的異常。更積極地重試通常不會對業(yè)務(wù)邏輯造成損害,但這是浪費(fèi),因?yàn)槿绻∈谴_定的,那么重試一些預(yù)先知道是致命的東西就會花費(fèi)時間。

Spring Retry提供了一些無狀態(tài)RetryPolicy的簡單通用實(shí)現(xiàn),例如SimpleRetryPolicy和上面示例中使用的TimeoutRetryPolicy

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

// 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
    }
});

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

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

回退策略

在短暫故障之后重試時,在重試之前稍作等待通常會有所幫助,因?yàn)橥ǔ9收鲜怯赡承﹩栴}引起的,而這些問題只能通過等待來解決,如果RetryCallback失敗,RetryTemplate可以根據(jù)適當(dāng)?shù)?b>BackoffPolicy暫停執(zhí)行。

public interface BackoffPolicy {

    BackOffContext start(RetryContext context);

    void backOff(BackOffContext backOffContext)
        throws BackOffInterruptedException;

}

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

監(jiān)聽器

對于跨多個不同重試的橫切關(guān)注點(diǎn),能夠接收額外的回調(diào)通常是有用的,為此,Spring Retry提供了RetryListener接口,RetryTemplate允許用戶注冊RetryListeners,在迭代期間,他們將使用RetryContext獲得回調(diào),并在可用的地方使用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回調(diào)出現(xiàn)在整個重試之前和之后,onError應(yīng)用于各個RetryCallback調(diào)用,close方法也可能接收到一個Throwable,如果出現(xiàn)錯誤,則是RetryCallback拋出的最后一個錯誤。

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

用于反射方法調(diào)用的監(jiān)聽器

當(dāng)處理用@Retryable注解的方法或用Spring AOP攔截的方法時,spring-retry提供了在RetryListener實(shí)現(xiàn)中詳細(xì)檢查方法調(diào)用的可能性。

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

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
        // ...
      }
    });
聲明式重試

有時候,有些業(yè)務(wù)處理你知道每次發(fā)生時都要重試,這方面的經(jīng)典示例是遠(yuǎn)程服務(wù)調(diào)用,Spring Retry提供了一個AOP攔截器,它將方法調(diào)用封裝在RetryOperations中正是出于這個目的。RetryOperationsInterceptor執(zhí)行攔截方法,并根據(jù)所提供的RetryTemplate中的RetryPolicy在失敗時重試。

用于重試代理的Java配置

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

@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毫秒之間進(jìn)行隨機(jī)回退,最多嘗試12次,還有一個stateful屬性(默認(rèn)為false)來控制重試是否有狀態(tài),要使用有狀態(tài)重試,攔截方法必須有參數(shù),因?yàn)樗鼈冇糜跇?gòu)造狀態(tài)的緩存鍵。

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

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

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

@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版引入了對某些屬性使用表達(dá)式的功能:

@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,不推薦使用模板表達(dá)式(#{...}),而支持簡單表達(dá)式字符串(message.contains("this can be retried"))。

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

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

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

額外依賴項

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

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

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

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

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


    
    


上面的示例在攔截器中使用默認(rèn)的RetryTemplate,要更改策略或監(jiān)聽器,只需要將RetryTemplate實(shí)例注入攔截器。

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/75697.html

相關(guān)文章

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

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

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

    摘要:指南無論你正在構(gòu)建什么,這些指南都旨在讓你盡快提高工作效率使用團(tuán)隊推薦的最新項目版本和技術(shù)。使用進(jìn)行消息傳遞了解如何將用作消息代理。安全架構(gòu)的主題指南,這些位如何組合以及它們?nèi)绾闻c交互。使用的主題指南以及如何為應(yīng)用程序創(chuàng)建容器鏡像。 Spring 指南 無論你正在構(gòu)建什么,這些指南都旨在讓你盡快提高工作效率 — 使用Spring團(tuán)隊推薦的最新Spring項目版本和技術(shù)。 入門指南 這些...

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

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

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

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

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

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

    wall2flower 評論0 收藏0

發(fā)表評論

0條評論

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