Имитация клиента и повторная попытка Spring

У меня есть успокаивающая служба, вызывающая внешнюю службу с помощью клиента Spring Cloud Feign.

@FeignClient(name = "external-service", configuration = FeignClientConfig.class)
public interface ServiceClient {

    @RequestMapping(value = "/test/payments", method = RequestMethod.POST)
    public void addPayment(@Valid @RequestBody AddPaymentRequest addPaymentRequest);

    @RequestMapping(value = "/test/payments/{paymentId}", method = RequestMethod.PUT)
    public ChangePaymentStatusResponse updatePaymentStatus(@PathVariable("paymentId") String paymentId,
            @Valid @RequestBody PaymentStatusUpdateRequest paymentStatusUpdateRequest);

}

Я заметил в своем лог-файле 3-4 раза за последние 3 месяца следующие ошибки:

json.ERROR_RESPONSE_BODY: в соединении отказано при выполнении POST http://external-service/external/payments json.message: Отправить платеж Добавить платеж Ошибка По другой причине: {ERROR_RESPONSE_BODY = В соединении отказано при выполнении POST http://external-service/external/payments, EVENT = ADD_PAYMENT_FAILURE, TRANSACTION_ID = XXXXXXX} {} json.EVENT: ADD_PAYMENT_FAILURE json.stack_trace: feign.RetryableException: в соединении отказано при выполнении POST http://external-service/external/payments на feign.FeignException.errorExecuting (FeignException.java:67) на feign.SynchronousMethodHandler.executeAndDecode (SynchronousMethodHandler.java:104) на feign.SynchronousMethod .invoke (SynchronousMethodHandler.java:76) в feign.ReflectiveFeign $ FeignInvocationHandler.invoke (Reflectiv eFeign.java:103)

Можно ли добавить Spring Retry в клиент Feign. То, что я хотел аннотировать addPayment операцию с помощью

@Retryable(value = {feign.RetryableException.class }, maxAttempts = 3, backoff = @Backoff(delay = 2000, multiplier=2))

Но это невозможно, какие еще варианты у меня есть?


person Satya    schedule 07.11.2017    source источник
comment
Согласно документации, это возможно ... в облаке. spring.io/spring-cloud-netflix/multi/ Я не могу заставить его работать.   -  person notAChance    schedule 06.11.2019


Ответы (4)


Вы можете добавить Retryer в FeignClientConfig

@Configuration
public class FeignClientConfig {

    @Bean
    public Retryer retryer() {
        return new Custom();
    }

}

class Custom implements Retryer {

    private final int maxAttempts;
    private final long backoff;
    int attempt;

    public Custom() {
        this(2000, 3);
    }

    public Custom(long backoff, int maxAttempts) {
        this.backoff = backoff;
        this.maxAttempts = maxAttempts;
        this.attempt = 1;
    }

    public void continueOrPropagate(RetryableException e) {
        if (attempt++ >= maxAttempts) {
            throw e;
        }

        try {
            Thread.sleep(backoff);
        } catch (InterruptedException ignored) {
            Thread.currentThread().interrupt();
        }
    }

    @Override
    public Retryer clone() {
        return new Custom(backoff, maxAttempts);
    }
}

Обновлено с помощью образца Retryer примера конфигурации на основе Retryer.Default.

person Jeff    schedule 07.11.2017
comment
Можете ли вы указать на образец кода, показывающий настраиваемый Retryer? Как настроить повторную попытку только для feign.RetryableException и максимальной попытки = 3 и периода задержки 2 секунды между повторными попытками - person Satya; 07.11.2017
comment
Вы можете просто реализовать свой собственный ретриер - person Jeff; 07.11.2017

Если вы используете ленту, вы можете установить свойства, вы можете использовать следующие свойства для повторной попытки:

myapp.ribbon.MaxAutoRetries=5
myapp.ribbon.MaxAutoRetriesNextServer=5
myapp.ribbon.OkToRetryOnAllOperations=true

Примечание. «Myapp» - это идентификатор вашей службы.

Ознакомьтесь с реализацией Github для рабочего примера

person Yogi    schedule 07.11.2017
comment
Повторить попытку нужно только для feign.RetryableException.class и только для внешнего клиента fign. Мое приложение содержит несколько фиктивных клиентов. для настроек ленты можем ли мы указать конкретный фиктивный клиент и класс исключения? - person Satya; 07.11.2017
comment
Для такого конкретного случая вам нужно перейти к FeignConfig, прикрепить его к классу FeignClient и выполнить логику - person Yogi; 07.11.2017

Добавьте это, если это может кому-то помочь. Я получал сброс соединения с помощью симуляции, так как на этом порту выполнялся какой-то неизвестный процесс. Попробуйте сменить порт. Обратитесь к этому, чтобы найти процесс, запущенный на порту

person Deekshith Anand    schedule 04.02.2021

Я решил это, создав оболочку поверх ServiceClient.

@Configuration
public class ServiceClient {

@Autowired
ServiceFeignClient serviceFeignClient;

@Retryable(value = { ClientReprocessException.class }, maxAttemptsExpression = "#{${retryMaxAttempts}}", backoff = @Backoff(delayExpression = "#{${retryDelayTime}}"))

public void addPayment( AddPaymentRequest addPaymentRequest){
    return serviceFeignClient.addPayment(addPaymentRequest);
 }    
}
person Vikky    schedule 15.06.2021