首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何计算Spring-Retry中CircuitBreaker的正确超时时间?

如何计算Spring-Retry中CircuitBreaker的正确超时时间?
EN

Stack Overflow用户
提问于 2017-12-14 18:13:39
回答 1查看 1.1K关注 0票数 1

我知道@CircuitBreaker注释应该如何工作,但不确定resetTimeout参数值。

我有一个应用程序,它每隔10秒就会请求其他外部服务。每个请求可能需要1-3秒。默认的三次尝试是可以的,所以我想openTimeout中的40秒应该也没问题。我决定将80秒设置为resetTimeout。据我所知,如果在40秒内发生3次故障,那么电路将在resetTimeout参数中指定的时间内断开(80秒)。

在测试过程中,我注意到如果电路是开放的,并且另一个请求进入,那么外部服务将不会被调用。这是可以的,但我期望在resetTimeout (80年代)之后,一个真正的服务将被调用,但从未发生过。

奇怪的是,如果电路是打开的,并且在resetTimeout(80s)期间不调用服务,则电路将复位。IMHO弹簧应该比较当前时间和断开电路的故障,当前看起来它将当前时间与上次请求进行比较。

我是不是误解了这个库?

服务:

代码语言:javascript
复制
  package test;

import org.springframework.retry.annotation.CircuitBreaker;
import org.springframework.retry.annotation.Recover;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestClientException;

@Component
class ConnectionService {

    @CircuitBreaker(include = { RestClientException.class }, openTimeout = 10_000, resetTimeout = 20_000)
    String doUpload(String payload) {
        if(payload.contentEquals("FAIL")) {
            throw new RestClientException("");
        }
        System.out.println("real service called");
        //callling external service....
        return payload;
    }

    @Recover
    public String recover(String payload) {
        return "recovered";
    }
}

测试:

代码语言:javascript
复制
package test;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.runners.MockitoJUnitRunner;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.retry.RetryCallback;
import org.springframework.retry.RetryContext;
import org.springframework.retry.RetryListener;
import org.springframework.retry.annotation.EnableRetry;

@RunWith(MockitoJUnitRunner.class)
public class SpringRetryTest {

    AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(
            SpringRetryTest.TestConfiguration.class);
    ConnectionService connectionService = context.getBean(ConnectionService.class);

    @Test
    public void testCircuitBreaker() throws InterruptedException {

        incorrectStep();
        incorrectStep();
        incorrectStep();
        incorrectStep();
        incorrectStep();
        System.out.println();
        System.out.println();
        System.out.println();

        final long l = System.currentTimeMillis();
        correctStep(l);
        correctStep(l);
        correctStep(l);
        correctStep(l);
        correctStep(l);
        correctStep(l);
        correctStep(l);
        correctStep(l);
        correctStep(l);
        correctStep(l);
        correctStep(l);
        correctStep(l);
        correctStep(l);
        correctStep(l);
        correctStep(l);
        correctStep(l);
        correctStep(l);
        correctStep(l);
        correctStep(l);
        correctStep(l);
        correctStep(l);
        correctStep(l);

        //wait more than resetTimeout
        System.out.println();
        System.out.println();
        System.out.println();
        Thread.sleep(21_000L);
        correctStep(l);

    }

    private void incorrectStep() throws InterruptedException {
        doFailedUpload(connectionService);
        Thread.sleep(1_000L);
        System.out.println();
    }

    private void correctStep(final long l) throws InterruptedException {
        doCorrectUpload(connectionService);
        Thread.sleep(1_000L);
        printTime(l);
    }

    private void printTime(final long l) {
        System.out.println(String.format("%d ms after last failure", (System.currentTimeMillis() - l)));
    }

    private void doFailedUpload(ConnectionService externalService) throws InterruptedException {
        System.out.println("before fail");
        externalService.doUpload("FAIL");
        System.out.println("after fail");
        Thread.sleep(900);
    }

    private void doCorrectUpload(ConnectionService externalService) throws InterruptedException {
        System.out.println("before ok");
        externalService.doUpload("");
        System.out.println("after ok");
        Thread.sleep(900);
    }

    @Configuration
    @EnableRetry
    protected static class TestConfiguration {

        @Bean
        public ConnectionService externalService() {
            return new ConnectionService();
        }

        @Bean
        public RetryListener retryListener1() {
            return new RetryListener() {
                @Override
                public <T, E extends Throwable> boolean open(final RetryContext retryContext, final RetryCallback<T, E> retryCallback) {
                    System.out.println("----/ ---- open, retry count:" + retryContext.getRetryCount());
                    return true;
                }

                @Override
                public <T, E extends Throwable> void close(final RetryContext retryContext, final RetryCallback<T, E> retryCallback, final Throwable throwable) {
                    System.out.println("---------- close, retry count:" + retryContext.getRetryCount());
                }

                @Override
                public <T, E extends Throwable> void onError(final RetryContext retryContext, final RetryCallback<T, E> retryCallback, final Throwable throwable) {
                    System.out.println("onError, retry count:" + retryContext.getRetryCount());
                }

            };
        }

    }

}

我使用的是OSX10.12.6,java 1.8.0_144 spring:4.2.3.RELEASE和spring-retry:1.2.1.RELEASE (我的同事也测试了1.2.2,结果是一样的)

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-07-22 14:53:36

问题已解决:https://github.com/spring-projects/spring-retry/issues/99

它还没有发布,目前以快照的形式提供。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/47810795

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档