版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/andy_zhang2007/article/details/88380456
本文是本人学习Hystrix
总结的第三篇,仍然是通过例子程序学习使用Hystrix
,模拟一个远程调用,并调整Hystrix
的执行参数和远程调用的参数观察超时发生时fallback
机制生效的情形,本应用特征如下 :
- 纯
java
项目 ;- 暂不涉及结合
Spring
使用,以便专注于Hystrix
自身;
- 暂不涉及结合
- 使用
junit
观察运行效果 ; - 使用
maven
管理依赖;
这里所模拟的远程调用通过
sleep
阻塞线程一段时间模拟一个耗时的远程调用,并无真正的远程调用发生。
1. pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>tut.zero</groupId>
<artifactId>hystrix</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>com.netflix.hystrix</groupId>
<artifactId>hystrix-core</artifactId>
<version>1.5.18</version>
</dependency>
<!-- test -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
</plugins>
</build>
</project>
2. 模拟一个远程服务调用
package tut.zero.middle;
/**
* 模拟一个远程服务调用
*/
public class MockRemoteService {
private long wait;
/**
* @param wait 模拟远程调用所消耗的时间,单位 : 毫秒
* @throws InterruptedException
*/
public MockRemoteService(long wait) {
this.wait = wait;
}
String execute() throws InterruptedException {
Thread.sleep(wait);
return "SUCCESS";
}
}
这是一个纯粹通过Java
模拟远程调用的类,通过Thread.sleep()
来模拟远程调用的执行耗时,而并不真正发生远程调用。该类和Hystrix
还没有任何关系。
2. 定义封装远程调用的Hystrix Command
,带fallback
实现
package tut.zero.middle;
import com.netflix.hystrix.HystrixCommand;
/**
* 封装一个模拟进行远程调用的 HystrixCommand, 返回结果设计为 String 类型
*/
public class MockRemoteServiceCommandWithFallback extends HystrixCommand<String> {
private MockRemoteService remoteService;
public MockRemoteServiceCommandWithFallback(Setter config, MockRemoteService remoteService) {
super(config);
this.remoteService = remoteService;
}
@Override
protected String run() throws Exception {
return remoteService.execute();
}
// 注意此处实现了 fallback 机制,也就是如果所模拟的远程调用失败,
// 则调用该方法而不是抛出 HystrixRuntimeException 异常
@Override
protected String getFallback() {
return "FALLBACK";
}
}
3. 测试运行定义的Hystrix Command
package tut.zero;
import tut.zero.middle.MockRemoteService;
import tut.zero.middle.MockRemoteServiceCommand;
import tut.zero.simple.CommandHelloWorld;
import com.netflix.hystrix.HystrixCommand;
import com.netflix.hystrix.HystrixCommandGroupKey;
import com.netflix.hystrix.HystrixCommandProperties;
import com.netflix.hystrix.HystrixThreadPoolProperties;
import com.netflix.hystrix.exception.HystrixRuntimeException;
import org.junit.Test;
import java.util.concurrent.Future;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.junit.Assert.assertThat;
public class HystrixTest {
/**
* 远程调用耗时超过了 HystrixCommand 所能容忍的时间限度,之后执行 fallback 机制
*/
@Test
public void testMockRemoteServiceCallWithFallback() {
HystrixCommand.Setter config = HystrixCommand.Setter
.withGroupKey(
HystrixCommandGroupKey.Factory.asKey("设置可容忍的超时时间小于远程方法的执行时间"));
HystrixCommandProperties.Setter commandProperties = HystrixCommandProperties.Setter();
commandProperties.withExecutionTimeoutInMilliseconds(1_000);
config.andCommandPropertiesDefaults(commandProperties);
assertThat(
new MockRemoteServiceCommandWithFallback(config, new MockRemoteService(2_000)).execute(),
equalTo("FALLBACK"));
}
}
该测试预期可以执行通过。远程调用设计为执行2秒,本地执行容忍超时设定为1秒,也就是说远程调用尚未结束,本地执行就失去耐心要超时了。但此时它并不抛出异常,因为我们在MockRemoteServiceCommandWithFallback
实现了fallback
机制,也就是其getFallback
方法的实现,所以此时MockRemoteServiceCommandWithFallback
在这种情况下会返回FALLBACK
,而不是抛出异常。