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. Я попробую его и поделитесь, если будут какие-либо материалы. –