Bootstrap

spring-retry注解方式使用(断路器,重试)

一. 在pom.xml中加入依赖


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

二.@CircuitBreaker

描述:标注需要短路的方法
参数
maxAttempts: 短路执行次数
openTimeout: 短路执行时间
resetTimeout:短路重试时间,当连续两次触发短路时,短路时间=openTimeout+resetTimeout
label:短路器的名字,系统唯一
include:需要短路的异常
exclude:不需要短路的异常

三.@Retryable

描述:标注需要重试的方法
参数
label: 重试的名字,系统唯一
maxAttempts:异常时重试次数
include:需要重试的异常
exclude:不需要重试的异常

四.@Recover

描述: 用来标注二触发短路,三触触发重试失败时,触发的恢复方法。该注解的反法必须和二,三注解的反法在同一个类中,详细见类RecoverAnnotationRecoveryHandler
参数:
标注方法入参: 可以有或者没有,如果有,则是异常时的异常
标注方法返回值: 可替代二或者三失败时返回值

五.示例程序

package com.reger.test.retry;

import java.util.concurrent.TimeUnit;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.context.event.EventListener;
import org.springframework.retry.annotation.Backoff;
import org.springframework.retry.annotation.CircuitBreaker;
import org.springframework.retry.annotation.EnableRetry;
import org.springframework.retry.annotation.Recover;
import org.springframework.retry.annotation.Retryable;

@SpringBootApplication
@EnableRetry(proxyTargetClass=true)
public class SpringBootStarterRetryDemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringBootStarterRetryDemoApplication.class, args);
    }

    @EventListener
    public void contextEvent(ContextRefreshedEvent contextEvent) throws InterruptedException {
        SpringBootStarterRetryDemoApplication demoApplication=contextEvent.getApplicationContext().getBean(SpringBootStarterRetryDemoApplication.class);
        System.err.println("尝试进入断路器方法,并触发异常");

        demoApplication.circuitBreaker(1);
        demoApplication.circuitBreaker(1);
        demoApplication.circuitBreaker(1);

        System.err.println("尝试进入断路器方法,在openTimeout时间内,触发异常超过3次,断路器打开,断路器方法不允许执行,直接执行恢复方法");
        demoApplication.circuitBreaker(2);
        TimeUnit.SECONDS.sleep(2);
        System.err.println("超过断路器半开时间resetTimeout,断路器半开,断路器方法运行允许3个访问进入");
        demoApplication.circuitBreaker(3);
        demoApplication.circuitBreaker(3);
        demoApplication.circuitBreaker(3);
        System.err.println("尝试进入断路器方法,在openTimeout时间内,触发异常超过3次,断路器打开,断路器方法不允许执行,直接执行恢复方法");
        demoApplication.circuitBreaker(4);
        TimeUnit.SECONDS.sleep(3);
        System.err.println("超过断路器再次超过半开时间openTimeout+resetTimeout,断路器半开,断路器方法运行允许三个访问进入");
        demoApplication.circuitBreaker(5);
        demoApplication.circuitBreaker(5);
        demoApplication.circuitBreaker(5);
        System.err.println("尝试进入断路器方法,在openTimeout时间内,触发异常超过3次,断路器打开,断路器方法不允许执行,直接执行恢复方法");
        demoApplication.circuitBreaker(6);
        TimeUnit.SECONDS.sleep(3);
        System.err.println("超过断路器再次超过半开时间openTimeout+resetTimeout,断路器半开,断路器方法运行允许三个访问进入");
        demoApplication.circuitBreaker(7);
        demoApplication.circuitBreaker(7);
        demoApplication.circuitBreaker(7);
        System.err.println("尝试进入断路器方法,在openTimeout时间内,触发异常超过3次,断路器打开,断路器方法不允许执行,直接执行恢复方法");
        demoApplication.circuitBreaker(8);
        TimeUnit.SECONDS.sleep(3);
        System.err.println("超过断路器再次超过半开时间openTimeout+resetTimeout,断路器半开,断路器方法运行允许三个访问进入,并且断路方法不再抛出异常,断路器关闭,方法可持续调用");
        demoApplication.circuitBreaker(9);
        demoApplication.circuitBreaker(9);
        demoApplication.circuitBreaker(9);
        demoApplication.circuitBreaker(9);
        demoApplication.circuitBreaker(9);
        demoApplication.circuitBreaker(9);

        System.err.println();
        System.err.println();
        System.err.println("开始重试");
        demoApplication.retryable(10);
        System.err.println("未抛出异常,");
        demoApplication.retryable(11);
    }

    @CircuitBreaker(maxAttempts=3,openTimeout=1000,resetTimeout=2000,label="test-CircuitBreaker",include=RuntimeException.class,exclude=Exception.class)
    public void circuitBreaker(int num) throws InterruptedException {
        System.err.print(" 进入断路器方法num="+num);
        if(num>8)return;
        Integer n=null;
        System.err.println(1/n);
    }


    @Retryable(label="test-Retryable" , maxAttempts=3,backoff=@Backoff(delay=1),include=RuntimeException.class,exclude=Exception.class)
    public void retryable(int num)  throws InterruptedException {
        System.err.println(" 进入重试方法num="+num);
        if(num>10)return;
        Integer n=null;
        System.err.println(1/n);
    }

    @Recover
    public void recover(NullPointerException exception) {
        System.err.println(" NullPointerException ....");
    }

    @Recover
    public void recover(RuntimeException exception) {
        System.err.println(" RuntimeException ....");
    }

    @Recover
    public void recover(Exception exception) {
        System.err.println(" exception ....");
    }

    @Recover
    public void recover(Throwable throwable) {
        System.err.println(" throwable ....");
    }
    @Recover
    public void recover() {
        System.err.println(" recover ....");
    }
}

六.示例输出的日志

尝试进入断路器方法,并触发异常
 进入断路器方法num=1 NullPointerException ....
 进入断路器方法num=1 NullPointerException ....
 进入断路器方法num=1 NullPointerException ....
尝试进入断路器方法,在openTimeout时间内,触发异常超过3次,断路器打开,断路器方法不允许执行,直接执行恢复方法
 NullPointerException ....
超过断路器半开时间resetTimeout,断路器半开,断路器方法运行允许3个访问进入
 进入断路器方法num=3 NullPointerException ....
 进入断路器方法num=3 NullPointerException ....
 进入断路器方法num=3 NullPointerException ....
尝试进入断路器方法,在openTimeout时间内,触发异常超过3次,断路器打开,断路器方法不允许执行,直接执行恢复方法
 NullPointerException ....
超过断路器再次超过半开时间openTimeout+resetTimeout,断路器半开,断路器方法运行允许三个访问进入
 进入断路器方法num=5 NullPointerException ....
 进入断路器方法num=5 NullPointerException ....
 进入断路器方法num=5 NullPointerException ....
尝试进入断路器方法,在openTimeout时间内,触发异常超过3次,断路器打开,断路器方法不允许执行,直接执行恢复方法
 NullPointerException ....
超过断路器再次超过半开时间openTimeout+resetTimeout,断路器半开,断路器方法运行允许三个访问进入
 进入断路器方法num=7 NullPointerException ....
 进入断路器方法num=7 NullPointerException ....
 进入断路器方法num=7 NullPointerException ....
尝试进入断路器方法,在openTimeout时间内,触发异常超过3次,断路器打开,断路器方法不允许执行,直接执行恢复方法
 NullPointerException ....
超过断路器再次超过半开时间openTimeout+resetTimeout,断路器半开,断路器方法运行允许三个访问进入,并且断路方法不再抛出异常,断路器关闭,方法可持续调用
 进入断路器方法num=9 进入断路器方法num=9 进入断路器方法num=9 进入断路器方法num=9 进入断路器方法num=9 进入断路器方法num=9

开始重试
 进入重试方法num=10
 进入重试方法num=10
 进入重试方法num=10
 NullPointerException ....
未抛出异常,
 进入重试方法num=11
;