一、建立SpringBoot測試項目,pom依賴如下
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.5.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.zhq</groupId>
<artifactId>hystrix</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>hystrix</name>
<description>Hystrix實作服務隔離、熔斷、降級案例</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.httpcomponents/httpclient -->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.47</version>
</dependency>
<dependency>
<groupId>com.netflix.hystrix</groupId>
<artifactId>hystrix-metrics-event-stream</artifactId>
<version>1.5.12</version>
</dependency>
<dependency>
<groupId>com.netflix.hystrix</groupId>
<artifactId>hystrix-javanica</artifactId>
<version>1.5.12</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
二、案例核心代碼
1)、建立TestController類編寫兩個沒有配置Hystrix的接口,一個配置了Hystrix的接口
@RestController
public class TestController {
@Autowired
private TestService testService;
/**
* 沒有配置Hystrix的API01
* @return
*/
@RequestMapping("/noHystrixApi01")
public Object noHystrixApi01(){
JSONObject baidu =testService.getBaidu();
System.out.println("目前線程名稱:" + Thread.currentThread().getName() + ",訂單服務調用會員服務:member:" + baidu);
return baidu;
}
/**
* 沒有配置Hystrix的API02
* @return
*/
@RequestMapping("/noHystrixApi02")
public Object noHystrixApi02(){
JSONObject baidu =testService.getBaidu();
System.out.println("目前線程名稱:" + Thread.currentThread().getName() + ",訂單服務調用會員服務:member:" + baidu);
return baidu;
}
/**
* 有配置Hystrix的API
* @return
*/
@RequestMapping("/hystrixApi")
public Object hystrixApi(){
return new HaveHystrixTestApiService(testService).execute();
}
}
2)、其中TestService代碼
@Service
public class TestService {
public JSONObject getBaidu() {
return HttpClientUtils.httpGet("http://www.baidu.com");
}
}
3)、配置 Hystrix的核心代碼HaveHystrixTestApiService
原理:
1、 使用線程池隔離可以完全隔離第三方應用,請求線程可以快速放回。 2、 請求線程可以繼續接受新的請求,如果出現問題線程池隔離是獨立的不會影響其他應用。
3、 當失敗的應用再次變得可用時,線程池将清理并可立即恢複,而不需要一個長時間的恢複。
4、 獨立的線程池提高了并發性
缺點:
線程池隔離的主要缺點是它們增加計算開銷(CPU)。每個指令的執行涉及到排隊、排程和上 下文切換都是在一個單獨的線程上運作的。
public class HaveHystrixTestApiService extends HystrixCommand<JSONObject> {
@Autowired
private TestService testService;
public HaveHystrixTestApiService(TestService testService) {
super(setter());
this.testService = testService;
}
private static Setter setter() {
// 服務分組
HystrixCommandGroupKey groupKey = HystrixCommandGroupKey.Factory.asKey("testGroup");
// 服務辨別
HystrixCommandKey commandKey = HystrixCommandKey.Factory.asKey("test");
// 線程池名稱
HystrixThreadPoolKey threadPoolKey = HystrixThreadPoolKey.Factory.asKey("test-pool");
// #####################################################
// 線程池配置 線程池大小為10,線程存活時間15秒 隊列等待的門檻值為100,超過100執行拒絕政策
HystrixThreadPoolProperties.Setter threadPoolProperties = HystrixThreadPoolProperties.Setter().withCoreSize(10)
.withKeepAliveTimeMinutes(15).withQueueSizeRejectionThreshold(100);
// ########################################################
// 指令屬性配置Hystrix 開啟逾時
HystrixCommandProperties.Setter commandProperties = HystrixCommandProperties.Setter()
// 采用線程池方式實作服務隔離
.withExecutionIsolationStrategy(HystrixCommandProperties.ExecutionIsolationStrategy.THREAD)
// 禁止
.withExecutionTimeoutEnabled(false);
return HystrixCommand.Setter.withGroupKey(groupKey).andCommandKey(commandKey).andThreadPoolKey(threadPoolKey)
.andThreadPoolPropertiesDefaults(threadPoolProperties).andCommandPropertiesDefaults(commandProperties);
}
@Override
protected JSONObject run() throws Exception {
JSONObject baidu = testService.getBaidu();
System.out.println("目前線程名稱:" + Thread.currentThread().getName() + ",訂單服務調用會員服務:member:" + baidu);
return baidu;
}
@Override
protected JSONObject getFallback() {
// 如果Hystrix發生熔斷,目前服務不可用,直接執行Fallback方法
System.out.println("系統錯誤!");
JSONObject jsonObject = new JSONObject();
jsonObject.put("code", 500);
jsonObject.put("msg", "系統錯誤!");
return jsonObject;
}
}
三、通過JMeter測試案例
1)、沒做接口保護的時候場景:
當并發請求noHystrixApi01接口線程池資源滿,導緻noHystrixApi02無法通路
啟動以後:
沒做接口保護時:雖然我們是并發請求api01但是導緻api02也無法通路
其中api01:
api02:
即他們共用一個線程池
2)壓測1)時如果通路有配置接口保護的hystrixApi接口
因為走的獨立線程池不受影響