springboot整合spring-retry的實現示例

1、背景

本系統調用外圍系統接口(http+json),但是發現有時外圍系統服務不太穩定,有時候會出現返回一串xml或者gateway bad的信息,導致調用失敗,基於這一原因,采用基於springboot,整合spring-retry的重試機制到系統工程中,demo已經放到github上。

2、解決方案

簡要說明:demo工程基於springboot,為瞭方便驗證,采用swagger進行測試驗證。

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>

重點說明:aop的gav必須有,否則會跑不起來。

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

2.2 applicat啟動類

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

說明:兩個標簽而已

@EnableRetry
@EnableSwagger2

2.3 controller類

/**
 * @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("重試測試類")
@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測試類(重點)

/**
 * @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被調用,時間:" + LocalTime.now());
        if (code == 0) {
            throw new Exception("異常拋出!");
        }
        System.out.println("retryTest被調用,情況對頭瞭!");

        return 200;
    }
    @Recover
    public int recover(Exception e) {
        System.out.println("回調方法執行,可以記錄日志到數據庫!!!!");
        //記日志到數據庫 或者調用其餘的方法
        return 400;
    }
}

**說明:**三個標簽

@Retryable註解
被註解的方法發生異常時會重試
value:指定發生的異常進行重試
include:和value一樣,默認空,當exclude也為空時,所有異常都重試
exclude:指定異常不重試,默認空,當include也為空時,所有異常都重試
maxAttemps:重試次數,默認3
backoff:重試補償機制,默認沒有

@Backoff註解說明
delay:指定延遲後重試
multiplier:指定延遲的倍數,比如delay=2000,multiplier=1.5時,第二次重試與第一次執行間隔:2秒;第三次重試與第二次重試間隔:3秒;第四次重試與第三次重試間隔:4.5秒。。。

@Recover
當重試到達指定次數時,被註解的方法將被回調,可以在該方法中進行日志處理。需要註意的是發生的異常和入參類型一致時才會回調

2.5 項目啟動

執行運行application,啟動成功,默認端口號:8080

2.6 使用swagger進行驗證

(1)swagger訪問地址:

http://localhost:8080/swagger-ui.html

(2)先驗證成功返回

先測試正常調用試試,code=1

調用返回:

(3)重試機制:code=0(重點)

為瞭更好的說明問題,參數配置增大一些:

@Retryable(value = Exception.class, maxAttempts = 5, backoff = @Backoff(delay = 2000, multiplier = 2))

執行效果

說明:

從執行效果看,總共執行5次,第二次跟第一次之間是2秒;第三次跟第二次之間是2*2=4秒;第四次與第三次之間是:2 乘以2乘以2=8秒,第五次與第四次之間是:2 乘以2乘以2乘以2=16秒,符合預期。

執行完成後,進入 @Recover標簽內容,可以進行日志記錄,以便後續定位問題。

github項目地址:https://github.com/ruanjianlaowang/springretry

到此這篇關於springboot整合spring-retry的實現示例的文章就介紹到這瞭,更多相關springboot整合spring-retry內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!

推薦閱讀: