Spring重试发送重复请求

Posted

技术标签:

【中文标题】Spring重试发送重复请求【英文标题】:Spring retry sending duplicate request 【发布时间】:2021-12-12 23:21:05 【问题描述】:

我可以在日志中看到 Spring retry 正在向远程服务器发送 2 个请求,并且两个请求都返回成功的响应。

我不知道背后的原因。

代码:

Class StatusClient

       @CircuitBreaker(maxAttemptsExpression = "#$remote.broadridge.circuitBreaker.maxAttempts",
                openTimeoutExpression = "#$remote.broadridge.circuitBreaker.openTimeout", resetTimeoutExpression = "#$remote.broadridge.circuitBreaker.resetTimeout")
        public Optional<JobStatusResponseDTO> getStatus(String account, String jobNumber) 
    
        client.post()
                    .uri(PATH)
                    .body(BodyInserters.fromValue(request))
                    .exchangeToMono(response -> 
                        if (response.statusCode() == HttpStatus.NO_CONTENT) 
                            return Mono.empty();
                         else if (isClientOrServerError(response)) 
                            return Mono.error(new RemoteClientException(String.format("status is not received: %s", response.statusCode())));
                        
    
                        stopWatch.stop();
                        log.info("time taken by the getStatus=[] for ", (stopWatch.getTotalTimeMillis()), request);
                        return response.bodyToMono(JobStatusResponseDTO.class);
                    )
                    .block();
    
            return Optional.ofNullable(block);

    
    Class status
    
     @Retryable(maxAttemptsExpression = "#$remote.retry.maxAttempts", backoff = @Backoff(delayExpression = "#$remote.retry.delay"))
        public Optional<JobStatusResponseDTO> getStatus(String jobNumber, String accountNumber) 
            return statusClient.getStatus(accountNumber, jobNumber);
        
    

application.yml 中的配置

circuitBreaker:
      maxAttempts: 3  # defalut 3
      openTimeout: 5000 # defalut 5000
      resetTimeout: 20000   # defalut 20000
    retry:
      maxAttempts: 3 # defalut 3
      delay: 1000 # defalut 1000

日志:

792 <14>1 2021-10-26T16:26:32.978917+00:00 -  2021-10-26 16:26:32.978 INFO [batch,ec40b8fe1f6a4cfb,06052e092b3f8e66] : time taken by the getStatus=[582] for JobStatusRequestDTO(account=12
        456, jobNumber=S123456)
        
        792 <14>1 2021-10-26T16:26:18.263121+00:00 2021-10-26 16:26:18.262 INFO [batch,ec40b8fe1f6a4cfb,21202725a0002bde] : time taken by the getStatus=[592] for JobStatusRequestDTO(account=12
        456, jobNumber=S123456)

两个请求相隔几秒钟。

编辑 1: 将断路器更改为最大尝试为 1。现在它正在重试 3 次。还有一个问题。似乎它只调用远程服务器一次而不是之后调用。 远程调用被封装在一个断路器中。

第一次尝试日志:

status is not received: 503 SERVICE_UNAVAILABLE

第二次尝试日志:

org.springframework.retry.ExhaustedRetryException: Retry exhausted after last attempt with no recovery path;

第三次尝试日志:

org.springframework.retry.ExhaustedRetryException: Retry exhausted after last attempt with no recovery path;

circuitBreaker:
      maxAttempts: 1
      openTimeout: 5000 # defalut 5000
      resetTimeout: 20000   # defalut 20000
    retry:
      maxAttempts: 3 # defalut 3
      delay: 1000 # defalut 1000

【问题讨论】:

我刚刚对其进行了测试,它按预期工作;我建议您在getStatus 中打印堆栈跟踪,以查看每次调用它的位置。 @GaryRussell 是的,它只重试了 3 次 bt 存在问题。请参阅编辑 1。 【参考方案1】:

这是因为您将默认的 retry.maxAttempts 设置为 3,延迟时间为 1000 毫秒。如果在提到的延迟时间内没有响应,Spring 将自动重试。因此,将 retry.maxAttemps 替换为 2 则不会给出多个响应。

您可以简单地在 application.properties 中粘贴以下行。

retry.maxAttempts=2
retry.maxDelay=100

另外,我建议你通过this。

【讨论】:

以上是关于Spring重试发送重复请求的主要内容,如果未能解决你的问题,请参考以下文章

FedEx Api:错误的请求错误,缺少或重复的参数。请修改您的请求,然后重试

防重幂等

Spring retry实践

求求你们了,别再重复造轮子了,一个 Spring 注解轻松搞定循环重试功能!

为啥我的 REST 服务 .NET 客户端会在没有身份验证标头的情况下发送每个请求,然后使用身份验证标头重试?

使用OkHttp3使用教程,实现getpost请求发送,自动重试,打印响应日志。