Test drive Hystrix Circuit Breaker configuration

允我心安 提交于 2019-12-19 11:39:09

问题


Our application is written in anit-fragile manner by implementing circuit breaker pattern using Hystrix.

The whole of the application is created using test driven practice but is stuck at the point where we need to implement the circuit breaker strategy by configuring the same on the methods.

Below is the sample configuration used by us -

@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")

Can anyone comment, if there is an available feature or opportunity to test drive it in my Integration Test (which loads the whole of WebApplicationContext, and hence is aware of all configurations available with the application)?

Or if this is not at all possible to be verified in my app context?

Any inputs will be of value.


回答1:


You can test your Hystrix circuit breaker configuration.

For instance, take a look at this example application with 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();
    }
}

Your configuration tests may look like this one:

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

In addition, if you want to test circuit breaker you can take a look at this test:

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


来源:https://stackoverflow.com/questions/38781398/test-drive-hystrix-circuit-breaker-configuration

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!