У меня проблема с настройкой резервных копий для фиктивных клиентов. Допустим, у меня есть такой клиент:
@FeignClient(name = "some-client", url = "${some-client.url}")
public interface SomeClient {
@GetMapping(value = "/api/some-endpoint", produces = MediaType.APPLICATION_JSON_VALUE)
List<SomeDto> searchForAllDtos(@RequestParam("param") String param);
}
Я настроил простую повторную загрузку следующим образом:
@Configuration
public class ClientConfiguration {
@Bean
public Retryer retryer(@Value("${http.retry.period}") long period,
@Value("${http.retry.maxPeriod}") long maxPeriod,
@Value("${http.retry.maxAttempts}") int maxAttempts) {
return new CustomRetryer(period, maxPeriod, maxAttempts);
}
@Bean
public ErrorDecoder decoder() {
return new CustomDecoder();
}
}
@Slf4j
class CustomRetryer extends Retryer.Default {
private final int maxAttempts;
private final long period;
private final long maxPeriod;
public CustomRetryer(long period, long maxPeriod, int maxAttempts) {
super(period, maxPeriod, maxAttempts);
this.period = period;
this.maxPeriod = maxPeriod;
this.maxAttempts = maxAttempts;
}
private CustomRetryer(CustomRetryer retryer) {
super(retryer.period, retryer.maxPeriod, retryer.maxAttempts);
this.period = retryer.period;
this.maxPeriod = retryer.maxPeriod;
this.maxAttempts = retryer.maxAttempts;
}
@Override
public void continueOrPropagate(RetryableException ex) {
super.continueOrPropagate(ex);
log.warn("Retrying HTTP request...");
}
@Override
public Retryer clone() {
return new CustomRetryer(this);
}
}
class CustomDecoder implements ErrorDecoder {
public Exception decode(String methodKey, Response response) {
if (response.status() > 499) {
throw new RetryableException(
response.status(),
String.format("Service unavailable (status code %s)", response.status()),
response.request().httpMethod(),
null,
response.request());
} else {
return new RuntimeException(
String.format("Error with status code %s received after HTTP request", response.status()));
}
}
}
Все работало хорошо, пока я не захотел добавить откат, когда вызов по-прежнему не работает после настройки максимальное количество попыток. Я сменил своего клиента следующим образом:
@FeignClient(name = "some-client", url = "${some-client.url}", fallback = SomeClientFallback.class)
public interface SomeClient {
// etc.
}
@Component
class SomeClientFallback implements SomeClient {
@Override
public List<SomeDto> searchForAllDtos(String param) {
return Collections.emptyList();
}
}
Он не работал, исключение все еще генерировалось вместо маршрутизации для обратного вызова, я прочитал, что hystrix должен быть включен, поэтому я добавил feign.hystrix.enabled=true
в свое приложение .properties файл. Кажется, все работает хорошо, после исследования и написания некоторых тестов я обнаружил, что повторная попытка используется только один раз, когда я настроил ее на 5 максимальных попыток. Похоже, есть конфликт с таймаутом hystrix, который по умолчанию установлен на 1000 мс. Я пытался увеличить его с помощью hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds
prop, но похоже, что это не работает. Я что-то пропустил?
Есть проект spring-retry
, который я мог бы использовать, но для этого нужно добавить аннотацию @Retryable
к методу evey, и я хотел бы, чтобы повторная попытка была по умолчанию для всех поддельных клиентов. Буду признателен за любую помощь и идеи.