springboot整合spring-retry的實(shí)現(xiàn)示例
1、背景
本系統(tǒng)調(diào)用外圍系統(tǒng)接口(http+json),但是發(fā)現(xiàn)有時(shí)外圍系統(tǒng)服務(wù)不太穩(wěn)定,有時(shí)候會(huì)出現(xiàn)返回一串xml或者gateway bad的信息,導(dǎo)致調(diào)用失敗,基于這一原因,采用基于springboot,整合spring-retry的重試機(jī)制到系統(tǒng)工程中,demo已經(jīng)放到github上。
2、解決方案
簡(jiǎn)要說(shuō)明:demo工程基于springboot,為了方便驗(yàn)證,采用swagger進(jìn)行測(cè)試驗(yàn)證。
2.1 pom文件
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.0</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.laowang</groupId>
<artifactId>springretry</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>springretry</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--retry-->
<dependency>
<groupId>org.springframework.retry</groupId>
<artifactId>spring-retry</artifactId>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
</dependency>
<!--swagger-->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.7.0</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.7.0</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
重點(diǎn)說(shuō)明:aop的gav必須有,否則會(huì)跑不起來(lái)。
<!--retry-->
<dependency>
<groupId>org.springframework.retry</groupId>
<artifactId>spring-retry</artifactId>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
</dependency>
2.2 applicat啟動(dòng)類(lèi)
package com.laowang.springretry;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.retry.annotation.EnableRetry;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
@EnableRetry
@EnableSwagger2
@SpringBootApplication
public class SpringretryApplication {
public static void main(String[] args) {
SpringApplication.run(SpringretryApplication.class, args);
}
}
說(shuō)明:兩個(gè)標(biāo)簽而已
@EnableRetry @EnableSwagger2
2.3 controller類(lèi)
/**
* @description: TODO
* @author Administrator
* @date 2021/6/2 14:55
* @version 1.0
*/
package com.laowang.springretry.controller;
import com.laowang.springretry.service.RetryService;
import io.swagger.annotations.Api;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@Api("重試測(cè)試類(lèi)")
@RestController
public class RetryController {
@Autowired
RetryService retryService;
@GetMapping("/testRetry")
public String testRetry(int code) throws Exception {
int result = retryService.retryTest(code);
return "result:" + result;
}
}
2.4 service測(cè)試類(lèi)(重點(diǎn))
/**
* @description: TODO
* @author Administrator
* @date 2021/6/2 12:23
* @version 1.0
*/
package com.laowang.springretry.service;
import org.springframework.retry.annotation.Backoff;
import org.springframework.retry.annotation.Recover;
import org.springframework.retry.annotation.Retryable;
import org.springframework.stereotype.Service;
import java.time.LocalTime;
@Service
public class RetryServiceImpl implements RetryService {
@Override
@Retryable(value = Exception.class, maxAttempts = 3, backoff = @Backoff(delay = 2000, multiplier = 1.5))
public int retryTest(int code) throws Exception {
System.out.println("retryTest被調(diào)用,時(shí)間:" + LocalTime.now());
if (code == 0) {
throw new Exception("異常拋出!");
}
System.out.println("retryTest被調(diào)用,情況對(duì)頭了!");
return 200;
}
@Recover
public int recover(Exception e) {
System.out.println("回調(diào)方法執(zhí)行,可以記錄日志到數(shù)據(jù)庫(kù)!?。?!");
//記日志到數(shù)據(jù)庫(kù) 或者調(diào)用其余的方法
return 400;
}
}
**說(shuō)明:**三個(gè)標(biāo)簽
@Retryable注解
被注解的方法發(fā)生異常時(shí)會(huì)重試
value:指定發(fā)生的異常進(jìn)行重試
include:和value一樣,默認(rèn)空,當(dāng)exclude也為空時(shí),所有異常都重試
exclude:指定異常不重試,默認(rèn)空,當(dāng)include也為空時(shí),所有異常都重試
maxAttemps:重試次數(shù),默認(rèn)3
backoff:重試補(bǔ)償機(jī)制,默認(rèn)沒(méi)有
@Backoff注解說(shuō)明
delay:指定延遲后重試
multiplier:指定延遲的倍數(shù),比如delay=2000,multiplier=1.5時(shí),第二次重試與第一次執(zhí)行間隔:2秒;第三次重試與第二次重試間隔:3秒;第四次重試與第三次重試間隔:4.5秒。。。
@Recover
當(dāng)重試到達(dá)指定次數(shù)時(shí),被注解的方法將被回調(diào),可以在該方法中進(jìn)行日志處理。需要注意的是發(fā)生的異常和入?yún)㈩?lèi)型一致時(shí)才會(huì)回調(diào)
2.5 項(xiàng)目啟動(dòng)

執(zhí)行運(yùn)行application,啟動(dòng)成功,默認(rèn)端口號(hào):8080

2.6 使用swagger進(jìn)行驗(yàn)證
(1)swagger訪問(wèn)地址:
http://localhost:8080/swagger-ui.html
(2)先驗(yàn)證成功返回

先測(cè)試正常調(diào)用試試,code=1

調(diào)用返回:

(3)重試機(jī)制:code=0(重點(diǎn))
為了更好的說(shuō)明問(wèn)題,參數(shù)配置增大一些:
@Retryable(value = Exception.class, maxAttempts = 5, backoff = @Backoff(delay = 2000, multiplier = 2))
執(zhí)行效果

說(shuō)明:
從執(zhí)行效果看,總共執(zhí)行5次,第二次跟第一次之間是2秒;第三次跟第二次之間是2*2=4秒;第四次與第三次之間是:2 乘以2乘以2=8秒,第五次與第四次之間是:2 乘以2乘以2乘以2=16秒,符合預(yù)期。
執(zhí)行完成后,進(jìn)入 @Recover標(biāo)簽內(nèi)容,可以進(jìn)行日志記錄,以便后續(xù)定位問(wèn)題。
github項(xiàng)目地址:https://github.com/ruanjianlaowang/springretry
到此這篇關(guān)于springboot整合spring-retry的實(shí)現(xiàn)示例的文章就介紹到這了,更多相關(guān)springboot整合spring-retry內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Spring實(shí)戰(zhàn)之使用ClassPathResource加載xml資源示例
這篇文章主要介紹了Spring實(shí)戰(zhàn)之使用ClassPathResource加載xml資源,結(jié)合實(shí)例形式分析了Spring使用ClassPathResource加載xml資源的具體實(shí)現(xiàn)步驟與相關(guān)操作技巧,需要的朋友可以參考下2019-12-12
Mybatis?mysql模糊查詢方式(CONCAT多個(gè)字段)及bug
這篇文章主要介紹了Mybatis?mysql模糊查詢方式(CONCAT多個(gè)字段)及bug,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-01-01
java封裝類(lèi)型與基礎(chǔ)類(lèi)型對(duì)比示例分析
這篇文章主要為大家介紹了java封裝類(lèi)型與基礎(chǔ)類(lèi)型對(duì)比示例分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-11-11
Java Web 實(shí)現(xiàn)QQ登錄功能一個(gè)帳號(hào)同一時(shí)間只能一個(gè)人登錄
對(duì)于一個(gè)帳號(hào)在同一時(shí)間只能一個(gè)人登錄,下文給大家介紹的非常詳細(xì),對(duì)java web qq 登錄功能感興趣的朋友一起看看吧2016-11-11
Java中List常用操作比f(wàn)or循環(huán)更優(yōu)雅的寫(xiě)法示例
List是Java中比較常用的集合類(lèi),關(guān)于List接口有很多實(shí)現(xiàn)類(lèi),下面這篇文章主要給大家介紹了關(guān)于Java中List常用操作比f(wàn)or循環(huán)更優(yōu)雅的寫(xiě)法,需要的朋友可以參考下2021-11-11
Java反射的應(yīng)用之動(dòng)態(tài)代理深入理解
這篇文章主要介紹了Java反射的應(yīng)用之動(dòng)態(tài)代理深入理解,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-09-09
Spring Security 密碼驗(yàn)證動(dòng)態(tài)加鹽的驗(yàn)證處理方法
小編最近在改造項(xiàng)目,需要將gateway整合security在一起進(jìn)行認(rèn)證和鑒權(quán),今天小編給大家分享Spring Security 密碼驗(yàn)證動(dòng)態(tài)加鹽的驗(yàn)證處理方法,感興趣的朋友一起看看吧2021-06-06
Spring入門(mén)配置和DL依賴(lài)注入實(shí)現(xiàn)圖解
這篇文章主要介紹了Spring入門(mén)配置和DL依賴(lài)注入實(shí)現(xiàn)圖解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-10-10

