代码之家  ›  专栏  ›  技术社区  ›  Wojciech Piotrowiak

如何计算断路器在春季重试时的正确超时?

  •  1
  • Wojciech Piotrowiak  · 技术社区  · 7 年前

    我知道怎么做 @CircuitBreaker 注释应该可以工作,但不确定 resetTimeout 参数值。

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

    在测试过程中,我注意到,如果电路开路,并且另一个请求传入,则不会调用外部服务。没关系,但我希望以后 重置超时 (80年代)将调用从未发生过的真正服务。

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

    我是否误解了这个图书馆的概念?

    服务:

      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";
        }
    }
    

    测试:

    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());
                    }
    
                };
            }
    
        }
    
    }
    

    我使用的是osx 10.12.6、java 1.8.0\u 144 spring:4.2.3。RELEASE和spring重试:1.2.1。版本(我的同事也测试了1.2.2,结果相同)

    1 回复  |  直到 7 年前
        1
  •  0
  •   Wojciech Piotrowiak    4 年前

    发布已解决: https://github.com/spring-projects/spring-retry/issues/99

    它还没有发布,目前可用作快照。

    推荐文章