spring retry 重試機制

Spring Retry 簡介

Spring 框架的一個模塊,它提供了自動重試失敗操作的功能。它使用基于注解的配置為 Spring 管理的 bean 提供聲明式重試支持。

通過使用 Spring Retry,您可以指定重試次數(shù)、重試的異常類型、重試之間的延遲以及與重試失敗操作相關(guān)的其他參數(shù)。這在處理不可靠的網(wǎng)絡(luò)連接或外部服務(wù)時非常有用。

要使用 Spring Retry,您需要將 spring-retry 依賴項添加到您的項目中,并使用 @Retryable 注解對需要重試的方法或類進行注解。您還可以使用 @Recover 注解自定義重試行為。

maven 依賴

<dependency>
    <groupId>org.springframework.retry</groupId>
    <artifactId>spring-retry</artifactId>
</dependency>

springboot 線程池 配置


/**
* @Package com.ympay.notify.config
* @Description: 線程池
* @author: jinghan
* @date 2019/5/14 11:01
*/
@Configuration
@EnableAsync
@EnableRetry
public class TaskPoolConfig {


    /**
     * 異步線程池
     * @return
     *
     * 核心線程數(shù)10:線程池創(chuàng)建時候初始化的線程數(shù)
     * 最大線程數(shù)20:線程池最大的線程數(shù),只有在緩沖隊列滿了之后才會申請超過核心線程數(shù)的線程
     * 緩沖隊列500:用來緩沖執(zhí)行任務(wù)的隊列
     * 允許線程的空閑時間60秒:當(dāng)超過了核心線程出之外的線程在空閑時間到達之后會被銷毀
     * 線程池名的前綴:設(shè)置好了之后可以方便我們定位處理任務(wù)所在的線程池
     * 線程池對拒絕任務(wù)的處理策略:這里采用了CallerRunsPolicy策略,當(dāng)線程池沒有處理能力的時候,該策略會直接在 execute 方法的調(diào)用線程中運行被拒絕的任務(wù);如果執(zhí)行程序已關(guān)閉,則會丟棄該任務(wù)
     *
     * 說明:setWaitForTasksToCompleteOnShutdown(true)該方法就是這里的關(guān)鍵,
     * 用來設(shè)置線程池關(guān)閉的時候等待所有任務(wù)都完成再繼續(xù)銷毀其他的Bean,
     * 這樣這些異步任務(wù)的銷毀就會先于Redis線程池的銷毀。同時,這里還設(shè)置了setAwaitTerminationSeconds(60),
     * 該方法用來設(shè)置線程池中任務(wù)的等待時間,如果超過這個時候還沒有銷毀就強制銷毀,以確保應(yīng)用最后能夠被關(guān)閉,而不是阻塞住。
     */
    @Bean("taskExecutor")
    public Executor taskExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(10);
        executor.setMaxPoolSize(20);
        executor.setQueueCapacity(500);
        executor.setKeepAliveSeconds(60);
        executor.setThreadNamePrefix("taskExecutor-");
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());


        executor.setWaitForTasksToCompleteOnShutdown(true);
        executor.setAwaitTerminationSeconds(60);


        return executor;
    }


}

異步線程池 + 重試機制

 @Async("taskExecutor")
    @Retryable(value = RetryException.class, maxAttempts = 5, backoff = @Backoff(delay = 30000L, multiplier = 2))
    public void autoRefresh(PlayerSettlementEntity entity) throws RetryException {
        if(PlayerSettleEnum.SettlementState.WAIT_SETTLEMENT.getCode().equals(entity.getSettlementState())){
            entity = settlementRefreshService.refresh(entity);
        }
        // 繼續(xù) 重試
        if(PlayerSettleEnum.SettlementState.WAIT_SETTLEMENT.getCode().equals(entity.getSettlementState())){
//            記錄當(dāng)前重試
            throw new RetryException("待同步 訂單號:"+entity.getSettlementSn());
        }
    }

在上面的示例中,@Retryable 注解指定了:

  • value 參數(shù):指定要重試的異常類型,這里指定為 IOException.class,表示只有在連接到外部服務(wù)時拋出 IOException 異常時才進行重試。
  • maxAttempts 參數(shù):指定最大重試次數(shù),這里指定為 5 次。
  • backoff 參數(shù):指定重試之間的延遲,這里指定為 3000 毫秒(即 1 秒),表示每次重試之間都要等待 3秒。
  • @EnableRetry 注釋添加到我們的 @Configuration 類 啟用 Spring Retry
  • @Backoff注解包括以下參數(shù):
  1. delay:指定在重試之間等待的時間量。默認為1000毫秒。
  2. multiplier:指定用于計算下一次重試之間的延遲時間的倍數(shù)。
    例如,如果當(dāng)前重試的延遲時間為1000毫秒,且倍數(shù)為2,則下一次重試之間的延遲時間將為2000毫秒。默認為1。
  3. random:指定是否在計算下一次重試之間的延遲時間時使用隨機化。默認為false。
  4. maxDelay:指定延遲時間的最大值。如果下一次重試之間的計算延遲時間大于此值,則使用此值。默認為Long.MAX_VALUE。
  5. vmultiplierExpression:指定用于計算下一次重試之間的延遲時間的表達式,可以包括${}占位符和EL表達式。默認為"",即不使用表達式。
    使用@Backoff注解可以讓重試策略更加靈活和可配置。

最大嘗試次數(shù)失敗后調(diào)用的方法

在指定方法上標(biāo)記@Recover來開啟重試失敗后調(diào)用的方法(注意,需跟重處理方法在同一個類中)


/**
在指定方法上標(biāo)記@Recover來開啟重試失敗后調(diào)用的方法(注意,需跟重處理方法在同一個類中)
* 重試 日志記錄 防止控制臺打印異常
* @param e
*/
@Recover
public void recover(RetryException e) {
    logger.info(e.getMessage());
}

在上面的示例中,@Recover 注解指定了恢復(fù)方法

  • recover(),它將在重試失敗后調(diào)用,并且只有在拋出
  • RetryException 異常時才會調(diào)用?;謴?fù)方法可以返回默認值或執(zhí)行其他操作。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 在調(diào)用第三方接口或者使用mq時,會出現(xiàn)網(wǎng)絡(luò)抖動,連接超時等網(wǎng)絡(luò)異常,所以需要重試。為了使處理更加健壯并且不太容易出...
    aoho閱讀 15,398評論 1 10
  • 在日常開發(fā)中重試機制還是比較常用的,比如因網(wǎng)絡(luò)原因等引起的超時,必要的重試市必須的。那么在springboot中如...
    金色木葉楓閱讀 5,730評論 3 11
  • 在調(diào)用第三方接口或者使用mq時,會出現(xiàn)網(wǎng)絡(luò)抖動,連接超時等網(wǎng)絡(luò)異常,所以需要重試。為了使處理更加健壯并且不太容易出...
    jackcooper閱讀 1,820評論 0 11
  • 當(dāng)我們調(diào)用一個接口可能由于網(wǎng)絡(luò)等原因造成第一次失敗,再去嘗試就成功了,這就是重試機制,spring支持重試機制,并...
    二月_春風(fēng)閱讀 24,402評論 1 9
  • 有些場景需要我們對一些異常情況下面的任務(wù)進行重試,比如:調(diào)用遠程的RPC/RestTemplate或者Feign服...
    梅西愛騎車閱讀 3,667評論 0 14

友情鏈接更多精彩內(nèi)容