springboot重試策略
前言
在我們日常開發中,會遇到比如A服務呼叫B服務RPC超時、獲取鎖失敗等場景,我們需要進行重試操作,為了不侵入程式碼優雅的進行重試,我們可以利用
Spring
提供的spring-retry
元件來實現。
開始
- 引入依賴
核心依賴spring-retry
,另外因為spring的retry底層是以AOP實現的,我們也需要引入aspectj
<dependency>
<groupId>org.springframework.retry</groupId>
<artifactId>spring-retry</artifactId>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.5</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.9.5</version>
</dependency>
- 開啟
@EnableRetry
支援
@EnableRetry
支援方法和類、介面、列舉級別的重試
@SpringBootApplication
@EnableRetry
public class SpringbootRetryApplication {
public static void main(String[] args) {
SpringApplication.run(SpringbootRetryApplication.class, args);
}
}
- 編寫重試service服務
@Retryable
引數說明:
- value:指定異常進行重試
- maxAttempts:重試次數,預設3次
- backoff:補償策略
- include:和value一樣,預設空,當exclude也為空時,所有異常都重試
- exclude:指定異常不重試,預設空,當include也為空時,所有異常都重試
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.remoting.RemoteAccessException;
import org.springframework.remoting.RemoteTimeoutException;
import org.springframework.retry.annotation.Backoff;
import org.springframework.retry.annotation.Recover;
import org.springframework.retry.annotation.Retryable;
import org.springframework.stereotype.Service;
/**
* @author lb
*/
@Service
public class RetryService {
private static final Logger LOGGER = LoggerFactory.getLogger(RetryService.class);
@Retryable(
// 指定發生的異常進行重試
value = {RemoteAccessException.class, RemoteTimeoutException.class} ,
// 重試次數
maxAttempts = 3,
// 補償策略 delay:延遲多久執行補償機制,multiplier:指定延遲的倍數,比如delay=5000,multiplier=2時,第一次重試為5秒後,第二次為10秒,第三次為20秒
backoff = @Backoff(delay = 5000L,multiplier = 2)
)
public String call(){
LOGGER.info("執行重試方法.....");
// throw new RemoteAccessException("RPC訪問異常");
throw new RemoteTimeoutException("RPC呼叫超時異常");
}
@Recover
public String recover(RemoteAccessException e){
LOGGER.info("最終重試失敗,執行RemoteAccess補償機制 error : {}",e.getMessage());
return "ok";
}
@Recover
public String recover(RemoteTimeoutException e){
LOGGER.info("最終重試失敗,執行RemoteTimeout補償機制 error : {}",e.getMessage());
return "ok";
}
}
有幾點需要注意的地方:
- 重試機制的
service
服務必須單獨建立一個class
,不能寫在介面的實現類裡,否則會丟擲ex @Retryable
是以AOP實現的,所以如果@Retryable
標記的方法被其他方法呼叫了,則不會進行重試。recover
方法的返回值型別必須和call()
方法的返回值型別一致
測試
- 編寫測試類
import com.lb.springboot.retry.service.RetryService;
import org.hamcrest.MatcherAssert;
import org.hamcrest.Matchers;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class SpringbootRetryApplicationTests {
@Autowired
private RetryService retryService;
@Test
public void testRetry(){
String result = retryService.call();
MatcherAssert.assertThat(result, Matchers.is("ok"));
}
}
- 執行結果:
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.2.4.RELEASE)
2020-12-17 14:15:58.083 INFO 71362 --- [ main] c.l.s.r.SpringbootRetryApplicationTests : Starting SpringbootRetryApplicationTests on yunnashengdeMacBook-Pro.local with PID 71362 (started by yunnasheng in /Users/yunnasheng/work/github-workspace/springboot-retry)
2020-12-17 14:15:58.086 INFO 71362 --- [ main] c.l.s.r.SpringbootRetryApplicationTests : No active profile set, falling back to default profiles: default
2020-12-17 14:15:59.238 INFO 71362 --- [ main] o.s.s.concurrent.ThreadPoolTaskExecutor : Initializing ExecutorService 'applicationTaskExecutor'
2020-12-17 14:15:59.470 INFO 71362 --- [ main] c.l.s.r.SpringbootRetryApplicationTests : Started SpringbootRetryApplicationTests in 1.686 seconds (JVM running for 2.582)
2020-12-17 14:15:59.668 INFO 71362 --- [ main] c.l.s.retry.service.RetryService : 執行重試方法.....
2020-12-17 14:16:04.674 INFO 71362 --- [ main] c.l.s.retry.service.RetryService : 執行重試方法.....
2020-12-17 14:16:14.675 INFO 71362 --- [ main] c.l.s.retry.service.RetryService : 執行重試方法.....
2020-12-17 14:16:14.676 INFO 71362 --- [ main] c.l.s.retry.service.RetryService : 最終重試失敗,執行RemoteTimeout補償機制 error : RPC呼叫超時異常
「其他文章」
- Servlet4.0 XML 模板
- Java讀取properties獲取所有配置並生根據key value成SQL
- 無法訪問GitHub的解決方案
- SpringCloud註冊中心-Eureka
- ohmyzsh主題修改
- 解決redis啟動時的三個警告
- AOP實現監控方法執行耗時
- 如何檢視Java原始碼中的native方法的原始碼?
- tomcat bio nio apr 模式效能測試與個人看法
- 使用 assh 來管理 SSH config
- 你真的瞭解GC嗎?
- 深入探討Hotspot虛擬機器在Java堆中物件建立、佈局和訪問的過程
- 解決IDEA無法debug的問題
- Restore IDE settings 重置IDEA所有配置
- Apache Maven Resources Plugin 某些檔案無法複製到 target目錄
- springboot整合druid對密碼加密
- Arthas小工具學習
- JVM棧調優與實戰
- JVM引數配置與應用測試
- JVM監控及故障排查