本系列代码地址:https://github.com/JoJoTec/sp...

咱们持续上一节针对咱们的重试进行测试

验证针对可重试的办法响应超时异样重试正确

咱们能够通过 httpbin.org 的 /delay/响应工夫秒 来实现申请响应超时。例如 /delay/3 就会提早三秒后返回。这个接口也是能够承受任何类型的 HTTP 申请办法。

咱们先来指定对于 Feign 超时的配置 Options:

//SpringExtension也蕴含了 Mockito 相干的 Extension,所以 @Mock 等注解也失效了@ExtendWith(SpringExtension.class)@SpringBootTest(properties = {        //敞开 eureka client        "eureka.client.enabled=false",        //默认申请重试次数为 3        "resilience4j.retry.configs.default.maxAttempts=3",        //指定默认响应超时为 2s        "feign.client.config.default.readTimeout=2000",})@Log4j2public class OpenFeignClientTest {    @SpringBootApplication    @Configuration    public static class App {        @Bean        public DiscoveryClient discoveryClient() {            //模仿两个服务实例            ServiceInstance service1Instance1 = Mockito.spy(ServiceInstance.class);            ServiceInstance service1Instance3 = Mockito.spy(ServiceInstance.class);            Map<String, String> zone1 = Map.ofEntries(                    Map.entry("zone", "zone1")            );            when(service1Instance1.getMetadata()).thenReturn(zone1);            when(service1Instance1.getInstanceId()).thenReturn("service1Instance1");            when(service1Instance1.getHost()).thenReturn("httpbin.org");            when(service1Instance1.getPort()).thenReturn(80);            DiscoveryClient spy = Mockito.spy(DiscoveryClient.class);            //微服务 testService1 有一个实例即 service1Instance1            Mockito.when(spy.getInstances("testService1"))                    .thenReturn(List.of(service1Instance1));            return spy;        }    }}

咱们别离定义会超时和不会超时的接口:

@FeignClient(name = "testService1", contextId = "testService1Client")public interface TestService1Client {    @GetMapping("/delay/1")    String testGetDelayOneSecond();    @GetMapping("/delay/3")    String testGetDelayThreeSeconds();}

编写测试,还是通过获取调用负载平衡获取实例的次数确定申请调用了多少次。

@Testpublic void testTimeOutAndRetry() throws InterruptedException {    Span span = tracer.nextSpan();    try (Tracer.SpanInScope cleared = tracer.withSpanInScope(span)) {        //避免断路器影响        circuitBreakerRegistry.getAllCircuitBreakers().asJava().forEach(CircuitBreaker::reset);        long l = span.context().traceId();        RoundRobinWithRequestSeparatedPositionLoadBalancer loadBalancerClientFactoryInstance                = (RoundRobinWithRequestSeparatedPositionLoadBalancer) loadBalancerClientFactory.getInstance("testService1");        AtomicInteger atomicInteger = loadBalancerClientFactoryInstance.getPositionCache().get(l);        int start = atomicInteger.get();        //不超时,则不会有重试,也不会有异样导致 fallback        String s = testService1Client.testGetDelayOneSecond();        //没有重试,只会申请一次        Assertions.assertEquals(1, atomicInteger.get() - start);        //避免断路器影响        circuitBreakerRegistry.getAllCircuitBreakers().asJava().forEach(CircuitBreaker::reset);        start = atomicInteger.get();        //超时,并且办法能够重试,所以会申请 3 次        try {            s = testService1Client.testGetDelayThreeSeconds();        } catch(Exception e) {}        Assertions.assertEquals(3, atomicInteger.get() - start);    }}

验证针对不可重试的办法响应超时异样不能重试

对于 GET 办法,咱们默认是能够重试的。然而个别扣款这种波及批改申请的接口,咱们会应用其余办法例如 POST。这一类办法个别申请超时咱们不会间接重试的。咱们还是通过 httporg.bin 的提早接口进行测试:

@FeignClient(name = "testService1", contextId = "testService1Client")public interface TestService1Client {    @PostMapping("/delay/3")    String testPostDelayThreeSeconds();}

编写测试,还是通过获取调用负载平衡获取实例的次数确定申请调用了多少次。

@Testpublic void testTimeOutAndRetry() throws InterruptedException {    Span span = tracer.nextSpan();    try (Tracer.SpanInScope cleared = tracer.withSpanInScope(span)) {        //避免断路器影响        circuitBreakerRegistry.getAllCircuitBreakers().asJava().forEach(CircuitBreaker::reset);        long l = span.context().traceId();        RoundRobinWithRequestSeparatedPositionLoadBalancer loadBalancerClientFactoryInstance                = (RoundRobinWithRequestSeparatedPositionLoadBalancer) loadBalancerClientFactory.getInstance("testService1");        AtomicInteger atomicInteger = loadBalancerClientFactoryInstance.getPositionCache().get(l);        int start = atomicInteger.get();        //不超时,则不会有重试,也不会有异样导致 fallback        String s = testService1Client.testPostDelayThreeSeconds();        //没有重试,只会申请一次        Assertions.assertEquals(1, atomicInteger.get() - start);    }}
微信搜寻“我的编程喵”关注公众号,每日一刷,轻松晋升技术,斩获各种offer