Как правильно настроить откат и повторную загрузку для @FeignClient? - PullRequest
1 голос
/ 09 июля 2020

У меня проблема с настройкой резервных копий для фиктивных клиентов. Допустим, у меня есть такой клиент:

@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, и я хотел бы, чтобы повторная попытка была по умолчанию для всех поддельных клиентов. Буду признателен за любую помощь и идеи.

...