#spring-boot #retrofit2 #spring-retry
Вопрос:
Недавно я добавил spring @Retryable
для обработки 502 ошибок вместо соответствующих ответов с целевого сервера. (с дооснащением2).
Ниже приведен просто псевдокод, но исходный код обрабатывает исключения аналогичным образом.
class BadGatewayException : RuntimeException
@Retryable(include = [BadGatewayException::class])
class A {
private fun handle(block: () -> Call<T>): T {
try {
val response = val response = block().execute()
...
if (response.code() == 502) {
throw BadGatewayException("The server suffers temporary connection problems.")
}
...
} catch(e: Exception) {
throw RuntimeException("a system error has occurred")
}
}
}
Я ожидал @Retryable
, что не буду повторять попытку, так как BadGatewayException
то, что происходит с 502, будет RuntimeException
сразу же завернуто в блок захвата, а затем брошено. Но, когда он был протестирован, казалось, что он следует этому шагу
- попробуйте получить ответ на запрос на модернизацию
- 502 происходит
BadGatewayException
брошенный- повторите попытку (3 по умолчанию) — здесь каким-то образом поймано исключение BadGatewayException
RuntimeException
брошенный
Дело в том, @Retryable
предполагается ли перехватывать какие-либо исключения таким образом? Или я что-то здесь упускаю?
Ответ №1:
SimpleRetryPolicy
Используемое аннотацией не пересекает cause
цепочку для поиска классифицированных исключений; только исключение верхнего уровня сравнивается со списком классифицированных.
Вам придется подключить свой собственный RetryInterceptor
с соответствующим образом настроенным RetryTemplate
и. SimpleRetryPolicy
/**
* Create a builder for a stateless retry interceptor.
* @return The interceptor builder.
*/
public static StatelessRetryInterceptorBuilder stateless() {
return new StatelessRetryInterceptorBuilder();
}
RetryInterceptorBuilder.stateless()
.retryPolicy(new SimpleRetryPolicy(...))
.build();
Видеть
/**
* Create a {@link SimpleRetryPolicy} with the specified number of retry attempts. If
* traverseCauses is true, the exception causes will be traversed until a match or the
* root cause is found. The default value indicates whether to retry or not for
* exceptions (or super classes thereof) that are not found in the map.
* @param maxAttempts the maximum number of attempts
* @param retryableExceptions the map of exceptions that are retryable based on the
* map value (true/false).
* @param traverseCauses true to traverse the exception cause chain until a classified
* exception is found or the root cause is reached.
* @param defaultValue the default action.
*/
public SimpleRetryPolicy(int maxAttempts, Map<Class<? extends Throwable>, Boolean> retryableExceptions,
boolean traverseCauses, boolean defaultValue) {
( defaultValue = true
и Map.of(BadGatewayException.class, false)
).
Задайте имя компонента перехватчика в свойстве interceptor
аннотации.