0

我們的應用程序是通過使用Hystrix實現斷路器模式以非常脆弱的方式編寫的。測試驅動器Hystrix斷路器配置

整個應用程序都是使用測試驅動的實踐創建的,但是我們需要通過在方法上配置相同的方法來實現斷路器策略。

下面是我們所使用的示例配置 -

@HystrixCommand(commandProperties = { 
     @HystrixProperty(name = "circuitBreaker.enabled", value = "true"), 
     @HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value = "8"), 
     @HystrixProperty(name = "circuitBreaker.errorThresholdPercentage", value = "25"), 
     @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "2000")}, 
     fallbackMethod = "retrieveMapFallback") 

任何人都可以評論,如果有可用的功能或機會去試駕它在我的集成測試(它加載了整個的WebApplicationContext的,因此,是否知道該應用程序可用的所有配置)?

或者如果這在我的應用上下文中不可能被驗證?

任何投入都是有價值的。

回答

1

您可以測試您的Hystrix斷路器配置。

例如,看看這個示例應用程序與Spring Boot 1.4

import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand; 
import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty; 
import org.springframework.boot.SpringApplication; 
import org.springframework.boot.autoconfigure.SpringBootApplication; 
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker; 
import org.springframework.stereotype.Component; 

@EnableCircuitBreaker 
@SpringBootApplication 
public class HystrixDemo { 

    public static void main(String[] args) { 
     SpringApplication.run(HystrixDemo.class, args); 
    } 

    @Component 
    static class MyService { 

     static final String COMMAND_KEY = "MyCommandKey"; 

     private final Outbound outbound; 

     MyService(Outbound outbound) { 
      this.outbound = outbound; 
     } 

     @HystrixCommand(
       commandKey = COMMAND_KEY, 
       commandProperties = { 
        @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "2016") 
       }) 
     void process() { 
      outbound.call(); 
     } 
    } 

    interface Outbound { 
     void call(); 
    } 
} 

你的配置測試可能看起來像這樣的:

import com.netflix.hystrix.HystrixCommandKey; 
import com.netflix.hystrix.HystrixCommandMetrics; 
import com.netflix.hystrix.HystrixCommandProperties; 
import org.junit.Before; 
import org.junit.Test; 
import org.junit.runner.RunWith; 
import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.boot.test.context.SpringBootTest; 
import org.springframework.boot.test.mock.mockito.MockBean; 
import org.springframework.test.context.junit4.SpringRunner; 

import static org.junit.Assert.assertTrue; 

@RunWith(SpringRunner.class) 
@SpringBootTest 
public class MyServiceCircuitBreakerConfigurationTests { 

    @Autowired 
    private HystrixDemo.MyService myService; 

    @MockBean 
    private HystrixDemo.Outbound outbound; 

    @Before 
    public void setup() { 
     warmUpCircuitBreaker(); 
    } 

    @Test 
    public void shouldHaveCustomTimeout() { 
     assertTrue(getCircuitBreakerCommandProperties().executionTimeoutInMilliseconds().get() == 2016); 
    } 

    private void warmUpCircuitBreaker() { 
     myService.process(); 
    } 

    public static HystrixCommandProperties getCircuitBreakerCommandProperties() { 
     return HystrixCommandMetrics.getInstance(getCommandKey()).getProperties(); 
    } 

    private static HystrixCommandKey getCommandKey() { 
     return HystrixCommandKey.Factory.asKey(HystrixDemo.MyService.COMMAND_KEY); 
    } 
} 

另外,如果你想測試斷路器你可以看看這個測試:

import com.netflix.config.ConfigurationManager; 
import com.netflix.hystrix.Hystrix; 
import com.netflix.hystrix.HystrixCircuitBreaker; 
import com.netflix.hystrix.HystrixCommandKey; 
import org.junit.Before; 
import org.junit.Test; 
import org.junit.runner.RunWith; 
import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.boot.test.context.SpringBootTest; 
import org.springframework.boot.test.mock.mockito.MockBean; 
import org.springframework.test.context.junit4.SpringRunner; 

import static org.junit.Assert.assertFalse; 
import static org.junit.Assert.assertTrue; 
import static org.junit.Assert.fail; 
import static org.mockito.BDDMockito.willThrow; 

@RunWith(SpringRunner.class) 
@SpringBootTest 
public class MyServiceCircuitBreakerTests { 

    @Autowired 
    private HystrixDemo.MyService myService; 

    @MockBean 
    private HystrixDemo.Outbound outbound; 

    @Before 
    public void setup() { 
     resetHystrix(); 
     warmUpCircuitBreaker(); 
     openCircuitBreakerAfterOneFailingRequest(); 
    } 

    @Test 
    public void shouldTripCircuit() throws InterruptedException { 
     willThrow(new RuntimeException()).given(outbound).call(); 

     HystrixCircuitBreaker circuitBreaker = getCircuitBreaker(); 

     // demonstrates circuit is actually closed 
     assertFalse(circuitBreaker.isOpen()); 
     assertTrue(circuitBreaker.allowRequest()); 

     try { 
      myService.process(); 
      fail("unexpected"); 
     } catch (RuntimeException exception) { 
      waitUntilCircuitBreakerOpens(); 
      assertTrue(circuitBreaker.isOpen()); 
      assertFalse(circuitBreaker.allowRequest()); 
     } 
    } 

    private void waitUntilCircuitBreakerOpens() throws InterruptedException { 
     /* one second is almost sufficient 
      borrowed from https://github.com/Netflix/Hystrix/blob/v1.5.5/hystrix-core/src/test/java/com/netflix/hystrix/HystrixCircuitBreakerTest.java#L140 
     */ 
     Thread.sleep(1000); 
    } 

    private void resetHystrix() { 
     Hystrix.reset(); 
    } 

    private void warmUpCircuitBreaker() { 
     myService.process(); 
    } 

    public static HystrixCircuitBreaker getCircuitBreaker() { 
     return HystrixCircuitBreaker.Factory.getInstance(getCommandKey()); 
    } 

    private static HystrixCommandKey getCommandKey() { 
     return HystrixCommandKey.Factory.asKey(HystrixDemo.MyService.COMMAND_KEY); 
    } 

    private void openCircuitBreakerAfterOneFailingRequest() { 
     ConfigurationManager.getConfigInstance().setProperty("hystrix.command." + HystrixDemo.MyService.COMMAND_KEY + ".circuitBreaker.requestVolumeThreshold", 1); 
    } 
} 
+0

這是一個很好的答案。感謝@ksokol。如果有任何投入,我會嘗試並分享。 –