试驾 Hystrix 断路器配置
Posted
技术标签:
【中文标题】试驾 Hystrix 断路器配置【英文标题】:Test drive Hystrix Circuit Breaker configuration 【发布时间】:2016-12-11 09:45:38 【问题描述】:我们的应用程序是通过使用 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);
【讨论】:
这是一个很好的答案。谢谢@ksokol。如果有任何意见,我会尝试并分享。以上是关于试驾 Hystrix 断路器配置的主要内容,如果未能解决你的问题,请参考以下文章