一尘不染

虚假客户和Spring重试

spring-boot

我有一个宁静的服务,使用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个月,我在日志文件中发现3-4次以下失败:

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.SynchronousMethodHandler.invoke(SynchronousMethodHandler.java:76)在feign.ReflectiveFeign
$ FeignInvocationHandler.invoke(Reflective) Java:103)

是否可以在Feign客户端上添加Spring Retry。我想用什么来注释addPayment操作

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

但这是不可能的,我还有什么其他选择?


阅读 270

收藏
2020-05-30

共1个答案

一尘不染

您可以添加RetryerFeignClientConfig

@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

2020-05-30