您好,登錄后才能下訂單哦!
怎么進行Spring-Retry的使用,針對這個問題,這篇文章詳細介紹了相對應的分析和解答,希望可以幫助更多想解決這個問題的小伙伴找到更簡單易行的方法。
在日常的一些場景中, 很多需要進行重試的操作.而spring-retry是spring提供的一個基于spring的重試框架,非常簡單好用.
<dependency> <groupId>org.springframework.retry</groupId> <artifactId>spring-retry</artifactId> <version>1.2.2.RELEASE</version> </dependency>
@Slf4j public class RetryDemo { public static boolean retryMethod(Integer param) { int i = new Random().nextInt(param); log.info("隨機生成的數:{}", i); if (1 == i) { log.info("為1,返回true."); return true; } else if (i < 1) { log.info("小于1,拋出參數異常."); throw new IllegalArgumentException("參數異常"); } else if (i > 1 && i < 10) { log.info("大于1,小于10,拋出參數異常."); return false; } else { //為其他 log.info("大于10,拋出自定義異常."); throw new RemoteAccessException("大于10,拋出自定義異常"); } } }
@Slf4j public class SpringRetryTest { /** * 重試間隔時間ms,默認1000ms */ private long fixedPeriodTime = 1000L; /** * 最大重試次數,默認為3 */ private int maxRetryTimes = 3; /** * 表示哪些異常需要重試 * key一定要為Throwable異常的子類 Class<? extends Throwable> * value為true表示需要重試 */ private Map<Class<? extends Throwable>, Boolean> exceptionMap = new HashMap<>(); @Test public void test() { // 1 添加異常的處理結果 true為需要重試 false為不需要重試 exceptionMap.put(RemoteAccessException.class, true); // 2 構建重試模板實例 RetryTemplate retryTemplate = new RetryTemplate(); // 3 設置重試回退操作策略 設置重試間隔時間 FixedBackOffPolicy backOffPolicy = new FixedBackOffPolicy(); backOffPolicy.setBackOffPeriod(fixedPeriodTime); // 4 設置重試策略 設置重試次數 設置異常處理結果 SimpleRetryPolicy retryPolicy = new SimpleRetryPolicy(maxRetryTimes, exceptionMap); //5 重試模板添加重試策略 添加回退操作策略 retryTemplate.setRetryPolicy(retryPolicy); retryTemplate.setBackOffPolicy(backOffPolicy); // 6 調用方法 Boolean resp = retryTemplate.execute( // RetryCallback 重試回調方法 retryContext -> { boolean result = RetryDemo.retryMethod(110); log.info("方法返回結果= {}", result); return result; }, // RecoveryCallback 異常回調方法 retryContext -> { // log.info("超過最大重試次數或者拋出了未定義的異常!!!"); return false; } ); log.info("接口返回結果 = {}",resp); } } /* // 查看結果 [main] INFO com.cf.demo.SpringRetry.SpringRetryTest - 超過最大重試次數或者拋出了未定義的異常!!! [main] INFO com.cf.demo.SpringRetry.SpringRetryTest - 接口返回結果 = false */
從代碼的書寫注解可以看到,RetryTemplate對象是Spring-Retry框架的重試執行者, 由它添加重試策略,回退操作策略等(注釋第五步).RetryTemplate執行重試方法(注釋第六步),通過execute方法, 傳入的參數是重試回調邏輯對象RetryCallback 和執行操作結束的恢復對象RecoveryCallback. 且可以切換添加的異常種類, 得知,只有添加過相應的異常,才會觸發重試操作,否則直接調用RecoveryCallback對象方法.
RetryTemplate的部分源碼:
/** * Keep executing the callback until it either succeeds or the policy dictates that we * stop, in which case the recovery callback will be executed. * * @see RetryOperations#execute(RetryCallback, RecoveryCallback) * @param retryCallback the {@link RetryCallback} * @param recoveryCallback the {@link RecoveryCallback} * @throws TerminatedRetryException if the retry has been manually terminated by a * listener. */ @Override public final <T, E extends Throwable> T execute(RetryCallback<T, E> retryCallback, RecoveryCallback<T> recoveryCallback) throws E { return doExecute(retryCallback, recoveryCallback, null); }
RetryTemplate添加重試策略源碼:
/** * Setter for {@link RetryPolicy}. * * @param retryPolicy the {@link RetryPolicy} */ public void setRetryPolicy(RetryPolicy retryPolicy) { this.retryPolicy = retryPolicy; }
RetryPolicy接口的實現類:
AlwaysRetryPolicy:允許無限重試,直到成功,可能會導致死循環
CircuitBreakerRetryPolicy:有熔斷功能的重試策略,需設置3個參數openTimeout、resetTimeout和delegate
CompositeRetryPolicy:組合重試策略,有兩種組合方式,樂觀組合重試策略是指只要有一個策略允許即可以重試,
悲觀組合重試策略是指只要有一個策略不允許即可以重試,但不管哪種組合方式,組合中的每一個策略都會執行
ExceptionClassifierRetryPolicy:設置不同異常的重試策略,類似組合重試策略,區別在于這里只區分不同異常的重試
NeverRetryPolicy:只允許調用RetryCallback一次,不允許重試
SimpleRetryPolicy:固定次數重試策略,默認重試最大次數為3次,RetryTemplate默認使用的策略
TimeoutRetryPolicy:超時時間重試策略,默認超時時間為1秒,在指定的超時時間內允許重試
RetryTemplate添加回退策略源碼:
/** * Setter for {@link BackOffPolicy}. * * @param backOffPolicy the {@link BackOffPolicy} */ public void setBackOffPolicy(BackOffPolicy backOffPolicy) { this.backOffPolicy = backOffPolicy; }
BackOffPolicy的實現類:
ExponentialBackOffPolicy:指數退避策略,需設置參數sleeper、initialInterval、maxInterval和multiplier,initialInterval指定初始休眠時間,默認100毫秒,maxInterval指定最大休眠時間,默認30秒,multiplier指定乘數,即下一次休眠時間為當前休眠時間*multiplier
ExponentialRandomBackOffPolicy:隨機指數退避策略,引入隨機乘數可以實現隨機乘數回退
FixedBackOffPolicy:固定時間的退避策略,需設置參數sleeper和backOffPeriod,sleeper指定等待策略,默認是Thread.sleep,即線程休眠,backOffPeriod指定休眠時間,默認1秒
NoBackOffPolicy:無退避算法策略,每次重試時立即重試
UniformRandomBackOffPolicy:隨機時間退避策略,需設置sleeper、minBackOffPeriod和maxBackOffPeriod,該策略在[minBackOffPeriod,maxBackOffPeriod之間取一個隨機休眠時間,minBackOffPeriod默認500毫秒,maxBackOffPeriod默認1500毫秒
<dependency> <groupId>org.springframework.retry</groupId> <artifactId>spring-retry</artifactId> <version>1.2.2.RELEASE</version> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.9.1</version> </dependency>
@Service @Slf4j public class SpringRetryDemo { /** * 重試所調用方法 * @return */ // delay=2000L表示延遲2秒 multiplier=2表示兩倍 即第一次重試2秒后,第二次重試4秒后,第三次重試8秒后 @Retryable(value = {RemoteAccessException.class}, maxAttempts = 3, backoff = @Backoff(delay = 2000L, multiplier = 2)) public boolean call(Integer param) { return RetryDemo.retryMethod(param); } /** * 超過最大重試次數或拋出沒有指定重試的異常 * @param e * @param param * @return */ @Recover public boolean recover(Exception e, Integer param) { log.info("請求參數為: ", param); log.info("超過最大重試次數或拋出沒有指定重試的異常, e = {} ", e.getMessage()); return false; } }
@SpringBootApplication @EnableRetry public class DemoApplication { public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); } }
@RunWith(SpringRunner.class) @SpringBootTest(classes = DemoApplication.class) @Slf4j public class DemoApplicationTests { @Autowired private SpringRetryDemo springRetryDemo; @Test public void testRetry() { boolean result = springRetryDemo.call(110); log.info("方法返回結果為: {}", result); } } /* 運行結果: 隨機生成的數:77 大于10,拋出自定義異常. 隨機生成的數:23 大于10,拋出自定義異常. 隨機生成的數:82 大于10,拋出自定義異常. 請求參數為: 超過最大重試次數或拋出沒有指定重試的異常, e = 大于10,拋出自定義異常 方法返回結果為: false */
注解說明:
@Enableretry注解,啟用重試功能(默認是否基于子類代理,默認是否, 即是基于Java接口代理)
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @EnableAspectJAutoProxy(proxyTargetClass = false) @Import(RetryConfiguration.class) @Documented public @interface EnableRetry { /** * Indicate whether subclass-based (CGLIB) proxies are to be created as opposed * to standard Java interface-based proxies. The default is {@code false}. * * @return whether to proxy or not to proxy the class */ boolean proxyTargetClass() default false; }
@Retryable注解, 標記的方法發生異常時會重試
value 指定發生的異常進行重試
include 與value一樣,默認為空,當exclude同時為空時,所有異常都重試
exclude 指定異常不重試,默認為空,當include同時為空,所有異常都重試
maxAttemps 重試次數,默認3
backoff 重試補充機制 默認是@Backoff()注解
@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). * @return exception types 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()}. * @since 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: * <pre class=code> * {@code "message.contains('you can retry this')"}. * </pre> * and * <pre class=code> * {@code "@someBean.shouldRetry(#root)"}. * </pre> * @return the expression. * @since 1.2 */ String exceptionExpression() default ""; }
@Backoff注解
delay 延遲多久后重試
multiplier 延遲的倍數
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Import(RetryConfiguration.class) @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.ExponentialBackOffPolicy#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. * @since 1.2 */ String delayExpression() default ""; /** <<<<<<< HEAD * An expression evaluating to the maximum wait (in milliseconds) between retries. * If less than the {@link #delay()} then ignored. ======= * 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. >>>>>>> Fix @Backoff JavaDocs - maxDelay * Overrides {@link #maxDelay()} * * @return the maximum delay between retries (default 0 = ignored) * @since 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) * @since 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; }
@Recover注解
當重試達到規定的次數后,被注解標記的方法將被調用, 可以在此方法中進行日志的記錄等操作.(該方法的入參類型,返回值類型需要和重試方法保持一致)
@Target({ ElementType.METHOD, ElementType.TYPE }) @Retention(RetentionPolicy.RUNTIME) @Import(RetryConfiguration.class) @Documented public @interface Recover { }
關于怎么進行Spring-Retry的使用問題的解答就分享到這里了,希望以上內容可以對大家有一定的幫助,如果你還有很多疑惑沒有解開,可以關注億速云行業資訊頻道了解更多相關知識。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。