SpringBoot技术实践-SpringRetry重试框架,java程序员面试笔试宝典

import com.codecoord.util.PrintUtil;

import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.Configuration;

import org.springframework.retry.RetryCallback;

import org.springframework.retry.RetryContext;

import org.springframework.retry.RetryListener;

import org.springframework.retry.backoff.ExponentialBackOffPolicy;

import org.springframework.retry.policy.SimpleRetryPolicy;

import org.springframework.retry.support.RetryTemplate;

@Configuration

public class RetryTemplateConfig {

/**

  • 注入retryTemplate

*/

@Bean

public RetryTemplate retryTemplate() {

RetryTemplate retryTemplate = new RetryTemplate();

/// 回退固定时间(秒)

/* FixedBackOffPolicy fixedBackOffPolicy = new FixedBackOffPolicy();

fixedBackOffPolicy.setBackOffPeriod(1000L);

retryTemplate.setBackOffPolicy(fixedBackOffPolicy);*/

// 指数回退(秒),第一次回退1s,第二次回退2s

ExponentialBackOffPolicy exponentialBackOffPolicy = new ExponentialBackOffPolicy();

exponentialBackOffPolicy.setInitialInterval(1000L);

exponentialBackOffPolicy.setMultiplier(2);

retryTemplate.setBackOffPolicy(exponentialBackOffPolicy);

// 重试策略

SimpleRetryPolicy retryPolicy = new SimpleRetryPolicy();

retryPolicy.setMaxAttempts(5);

retryTemplate.setRetryPolicy(retryPolicy);

// 设置监听器,open和close分别在启动和结束时执行一次

RetryListener[] listeners = {

new RetryListener() {

@Override

public <T, E extends Throwable> boolean open(RetryContext context, RetryCallback<T, E> callback) {

PrintUtil.print(“open”);

return true;

}

@Override

public <T, E extends Throwable> void close(RetryContext context, RetryCallback<T, E> callback,

Throwable throwable) {

PrintUtil.print(“close”);

}

@Override

public <T, E extends Throwable> void onError(RetryContext context, RetryCallback<T, E> callback,

Throwable throwable) {

PrintUtil.print(“onError”);

}

}

};

retryTemplate.setListeners(listeners);

return retryTemplate;

}

}

  1. 在controller中注入RetryTemplate使用,也可以是在service中

@RestController

public class SpringRetryController {

@Resource

private RetryTemplate retryTemplate;

private static int count = 0;

@RequestMapping("/retry")

public Object retry() {

try {

count = 0;

retryTemplate.execute((RetryCallback<Void, RuntimeException>) context -> {

// 业务代码

// …

// 模拟抛出异常

++count;

throw new RuntimeException(“抛出异常”);

});

} catch (RuntimeException e) {

System.out.println(“Exception”);

}

return "retry = " + count;

}

}

  1. 访问retry接口,然后观察日志输出

18:27:20.648 - http-nio-8888-exec-1 - open

18:27:20.649 - http-nio-8888-exec-1 - retryTemplate.execute执行

18:27:20.649 - http-nio-8888-exec-1 - onError

18:27:21.658 - http-nio-8888-exec-1 - retryTemplate.execute执行

18:27:21.658 - http-nio-8888-exec-1 - onError

18:27:23.670 - http-nio-8888-exec-1 - retryTemplate.execute执行

18:27:23.670 - http-nio-8888-exec-1 - onError

18:27:27.679 - http-nio-8888-exec-1 - retryTemplate.execute执行

18:27:27.679 - http-nio-8888-exec-1 - onError

18:27:35.681 - http-nio-8888-exec-1 - retryTemplate.execute执行

18:27:35.681 - http-nio-8888-exec-1 - onError

18:27:35.681 - http-nio-8888-exec-1 - close

三、EnableRetry

================================================================================

  1. @EnableRetry开启重试,在类上指定的时候方法将默认执行,重试三次

  2. 定义service,开启@EnableRetry注解和指定@Retryable,重试可以参考后面一节

import org.springframework.retry.annotation.Retryable;

public interface RetryService {

/**

  • 重试方法调用

*/

@Retryable

void retryServiceCall();

}

import org.springframework.retry.annotation.EnableRetry;

import org.springframework.stereotype.Service;

@EnableRetry

@Service

public class RetryServiceImpl implements RetryService {

@Override

public void retryServiceCall() {

PrintUtil.print(“方法调用…”);

throw new RuntimeException(“手工异常”);

}

}

  1. controller中注入service

@RequestMapping("/retryAnnotation")

public Object retryAnnotation() {

retryService.retryServiceCall();

return “retryAnnotation”;

}

  1. 将会默认重试

18:46:48.721 - http-nio-8888-exec-1 - 方法调用…

18:46:49.724 - http-nio-8888-exec-1 - 方法调用…

18:46:50.730 - http-nio-8888-exec-1 - 方法调用…

java.lang.RuntimeException: 手工异常

四、Retryable

==============================================================================

  1. 用于需要重试的方法上的注解

  2. 有以下几个属性

  • Retryable注解参数

  • value:指定发生的异常进行重试

  • include:和value一样,默认空,当exclude也为空时,所有异常都重试

  • exclude:指定异常不重试,默认空,当include也为空时,所有异常都重试

  • maxAttemps:重试次数,默认3

  • backoff:重试补偿机制,默认没有

  • @Backoff 注解 重试补偿策略

  • 不设置参数时,默认使用FixedBackOffPolicy(指定等待时间),重试等待1000ms

  • 设置delay,使用FixedBackOffPolicy(指定等待设置delay和maxDealy时,重试等待在这两个值之间均态分布)

  • 设置delay、maxDealy、multiplier,使用 ExponentialBackOffPolicy(指数级重试间隔的实现),multiplier即指定延迟倍数,比如delay=5000L,multiplier=2,则第一次重试为5秒,第二次为10秒,第三次为20秒

@Target({ ElementType.METHOD, ElementType.TYPE })

@Retention(RetentionPolicy.RUNTIME)

@Documented

public @interface Retryable {

/**

  • Retry interceptor bean name to be applied for retryable method. Is mutually

  • exclusive with other attributes.

  • @return the retry interceptor bean name

*/

String interceptor() default “”;

/**

  • Exception types that are retryable. Synonym for includes(). Defaults to empty (and

  • if excludes is also empty all exceptions are retried).

  • @return exception types to retry

*/

Class<? extends Throwable>[] value() default {};

/**

  • Exception types that are retryable. Defaults to empty (and if excludes is also

  • empty all exceptions are retried).

  • @return exception types to retry

*/

Class<? extends Throwable>[] include() default {};

/**

  • Exception types that are not retryable. Defaults to empty (and if includes is also

  • empty all exceptions are retried).

  • If includes is empty but excludes is not, all not excluded exceptions are retried

  • @return exception types not to retry

*/

Class<? extends Throwable>[] exclude() default {};

/**

  • A unique label for statistics reporting. If not provided the caller may choose to

  • ignore it, or provide a default.

  • @return the label for the statistics

*/

String label() default “”;

/**

  • Flag to say that the retry is stateful: i.e. exceptions are re-thrown, but the

  • retry policy is applied with the same policy to subsequent invocations with the

  • same arguments. If false then retryable exceptions are not re-thrown.

  • @return true if retry is stateful, default false

*/

boolean stateful() default false;

/**

  • @return the maximum number of attempts (including the first failure), defaults to 3

*/

int maxAttempts() default 3;

/**

  • @return an expression evaluated to the maximum number of attempts (including the first failure), defaults to 3

  • Overrides {@link #maxAttempts()}.

  • @date 1.2

*/

String maxAttemptsExpression() default “”;

/**

  • Specify the backoff properties for retrying this operation. The default is a

  • simple {@link Backoff} specification with no properties - see it’s documentation

  • for defaults.

  • @return a backoff specification

*/

Backoff backoff() default @Backoff();

/**

  • Specify an expression to be evaluated after the {@code SimpleRetryPolicy.canRetry()}

  • returns true - can be used to conditionally suppress the retry. Only invoked after

  • an exception is thrown. The root object for the evaluation is the last {@code Throwable}.

  • Other beans in the context can be referenced.

  • For example:

  • {@code “message.contains(‘you can retry this’)”}.

  • and

  • {@code “@someBean.shouldRetry(#root)”}.

  • @return the expression.

  • @date 1.2

*/

String exceptionExpression() default “”;

/**

  • Bean names of retry listeners to use instead of default ones defined in Spring context

  • @return retry listeners bean names

*/

String[] listeners() default {};

}

  1. 在需要重试的方法上配置对应的重试次数、重试异常的异常类型、设置回退延迟时间、重试策略、方法监听名称

@Target(ElementType.TYPE)

@Retention(RetentionPolicy.RUNTIME)

@Documented

public @interface Backoff {

/**

  • Synonym for {@link #delay()}.

  • @return the delay in milliseconds (default 1000)

*/

long value() default 1000;

/**

  • A canonical backoff period. Used as an initial value in the exponential case, and

  • as a minimum value in the uniform case.

  • @return the initial or canonical backoff period in milliseconds (default 1000)

*/

long delay() default 0;

/**

  • The maximimum wait (in milliseconds) between retries. If less than the

  • {@link #delay()} then the default of

  • {@value org.springframework.retry.backoff.ExponentialBackOffPolic

《一线大厂Java面试题解析+后端开发学习笔记+最新架构讲解视频+实战项目源码讲义》

【docs.qq.com/doc/DSmxTbFJ1cmN1R2dB】 完整内容开源分享

y#DEFAULT_MAX_INTERVAL}

  • is applied.

  • @return the maximum delay between retries (default 0 = ignored)

*/

long maxDelay() default 0;

/**

  • If positive, then used as a multiplier for generating the next delay for backoff.

  • @return a multiplier to use to calculate the next backoff delay (default 0 =

  • ignored)

*/

double multiplier() default 0;

/**

  • An expression evaluating to the canonical backoff period. Used as an initial value

  • in the exponential case, and as a minimum value in the uniform case. Overrides

  • {@link #delay()}.

  • @return the initial or canonical backoff period in milliseconds.

  • @date 1.2

*/

String delayExpression() default “”;

/**

  • An expression evaluating to the maximimum wait (in milliseconds) between retries.

  • If less than the {@link #delay()} then the default of

  • {@value org.springframework.retry.backoff.ExponentialBackOffPolicy#DEFAULT_MAX_INTERVAL}

  • is applied. Overrides {@link #maxDelay()}

  • @return the maximum delay between retries (default 0 = ignored)

  • @date 1.2

*/

String maxDelayExpression() default “”;

/**

  • Evaluates to a vaule used as a multiplier for generating the next delay for

  • backoff. Overrides {@link #multiplier()}.

  • @return a multiplier expression to use to calculate the next backoff delay (default

  • 0 = ignored)

  • @date 1.2

*/

String multiplierExpression() default “”;

/**

  • In the exponential case ({@link #multiplier()} > 0) set this to true to have the

  • backoff delays randomized, so that the maximum delay is multiplier times the

  • previous delay and the distribution is uniform between the two values.

  • @return the flag to signal randomization is required (default false)

*/

boolean random() default false;

}

@Component

public class PlatformClassService {

@Retryable(

// 重试异常的异常类型

value = {Exception.class},

// 最大重试次数

maxAttempts = 5,

// 设置回退延迟时间

backoff = @Backoff(delay = 500),

// 配置回调方法名称

listeners = “retryListener”

)

public void call() {

System.out.println(“call…”);

throw new RuntimeException(“手工异常”);

}

}

// 初始延迟2秒,然后之后验收1.5倍延迟重试,总重试次数4

@Retryable(value = {Exception.class}, maxAttempts = 4, backoff = @Backoff(delay = 2000L, multiplier = 1.5))

  1. 监听方法,在配置类中进行配置

/**

  • 注解调用

*/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值