今回も備忘録です。
このドキュメントについて
下記について記載していきます。
・@Retryableを利用したリトライ処理の実装
・RetryTemplateを利用したリトライ処理の実装
実行環境
・Java17
・springboot 3.0.2
実装
@Retryableを利用したリトライ処理の実装
@Retryable(retryFor= Exception.class, maxAttempts = 5, backoff = @Backoff(delay = 1000))
public ResponseEntity<String> retryTest() {
count = count + 1;
log.info("試行回数:" + count + "、時間:" + LocalDateTime.now());
throw new RuntimeException("処理失敗してます");
}
@Recover
public ResponseEntity<String> recover(Exception e) {
log.info(e.getMessage());
return ResponseEntity.ok("リトライ後のリカバリー");
}
説明:
- リトライしたいメソッドに@Retryableを付与することで、リトライが可能になる
引数部分に詳しい設定を行う。
・retryFor:リトライ対象のExceptionを設定
・maxAttempts:最大のリトライ回数を設定
(初回実行時も含めるので、上記例だと4回リトライすることになる)
・backoff:リトライ間隔の時間を設定できる
(上記例だと1秒。multiplierというのもあり、リトライする度に間隔を伸ばすことができる。)
2.@Recoverをメソッドに付与すると、リトライしてもダメだった場合のリカバリーができる
RetryTemplateを利用したリトライ処理の実装
複数箇所で同様のリトライ処理を入れたい場合は、こちらを利用するのがおすすめ。
@Bean(name = "normalTemplate")
public RetryTemplate normalTemplate() {
return RetryTemplate.
builder()
.maxAttempts(5)
.fixedBackoff(3000)
.retryOn(RuntimeException.class)
.build();
}
説明:
- リトライの設定に複雑さを求めないのであれば、RetryTemplateのbuilderでさくっと設定ができる。
- maxAttempts:最大リトライ回数
fixedBackoff:リトライ間隔
retryOn:リトライ対象のException
3.@BeanでDIコンテナに登録して、利用したいクラスで依存性注入してあげればどこでも利用できる
もう少し複雑な設定もできる。
@Configuration
public class RetryConfig {
@Bean
public SimpleRetryPolicy simpleRetryPolicy() {
var simpleRetryPolicy = new SimpleRetryPolicy();
simpleRetryPolicy.setMaxAttempts(5);
return simpleRetryPolicy;
}
@Bean
public FixedBackOffPolicy fixedBackOffPolicy() {
var fixedBackOffPolicy = new FixedBackOffPolicy();
fixedBackOffPolicy.setBackOffPeriod(3000);
return fixedBackOffPolicy;
}
@Bean
public ExceptionClassifierRetryPolicy exceptionClassifierRetryPolicy(SimpleRetryPolicy simpleRetryPolicy) {
var exceptionClassifierRetryPolicy = new ExceptionClassifierRetryPolicy();
exceptionClassifierRetryPolicy.setExceptionClassifier(set -> {
return set instanceof RuntimeException ? simpleRetryPolicy : new NeverRetryPolicy();
});
return exceptionClassifierRetryPolicy;
}
@Bean(name = "customTemplate")
public RetryTemplate retryTemplate(ExceptionClassifierRetryPolicy exceptionClassifierRetryPolicy, FixedBackOffPolicy fixedBackOffPolicy) {
var retryListener = new RetryListener() {
@Override
public <T, E extends Throwable> void onError(RetryContext context, RetryCallback<T, E> callback,
Throwable throwable) {
if (context.getRetryCount() ==3) {
throw new ExampleException("retryListerからのエラー出力", 500);
}
}
};
return RetryTemplate
.builder()
.customPolicy(exceptionClassifierRetryPolicy)
.customBackoff(fixedBackOffPolicy)
.withListener(retryListener)
.build();
}
}
説明:
1.SimpleRetryPolicyやFixedBackOffPolicyを汎用的に利用できるように@Beanで登録しておく。
2.ExceptionClassifierRetryPolicyでExceptionごとにretryPolicyを設定する。
例で言うと、RuntimeExceptionならSimpleRetryPolicyで、それ以外ならリトライしないNeverRetryPolicyを設定する。
3.RetryListenerはエラーが起こった時や、成功した時に処理を入れ込むことができる
上記だと、リトライカウントが3回目の時はExampleExceptionを投げる設定になっている
4.あとはRetryTemplateのbuilderで設定してあげれば終わり
まとめ
他システムとの通信時やできる限り失敗したくない処理の時には、必ず役に立つspringのRetry処理になるので知っておいて損はないです。
もっといい書き方とかあれば教えてほしいです。