Skip to content

Commit

Permalink
增加 Hystrix 入门示例(Hystrix Turbine)
Browse files Browse the repository at this point in the history
  • Loading branch information
YunaiV committed May 13, 2020
1 parent 9af1942 commit 8aeb88f
Show file tree
Hide file tree
Showing 14 changed files with 448 additions and 4 deletions.
74 changes: 74 additions & 0 deletions labx-23/labx-23-scn-hystrix-dashboard-turbine/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
<?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">
<parent>
<artifactId>labx-23</artifactId>
<groupId>cn.iocoder.springboot.labs</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

<artifactId>labx-23-scn-hystrix-dashboard-turbine</artifactId>

<properties>
<maven.compiler.target>1.8</maven.compiler.target>
<maven.compiler.source>1.8</maven.compiler.source>
<spring.boot.version>2.2.4.RELEASE</spring.boot.version>
<spring.cloud.version>Hoxton.SR1</spring.cloud.version>
</properties>

<!--
引入 Spring Boot、Spring Cloud、Spring Cloud Alibaba 三者 BOM 文件,进行依赖版本的管理,防止不兼容。
在 https://dwz.cn/mcLIfNKt 文章中,Spring Cloud Alibaba 开发团队推荐了三者的依赖关系
-->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>${spring.boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring.cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>

<dependencies>
<!-- 引入 SpringMVC 相关依赖,并实现对其的自动配置 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>

<!-- 引入 Spring Cloud Netflix Hystrix 相关依赖,将 Hystrix 作为服务保障组件,并实现对其的自动配置 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>

<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
</dependency>

<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-turbine</artifactId>
</dependency>

<!-- 引入 Spring Cloud Netflix Eureka Client 相关依赖,将 Eureka 作为注册中心的客户端,并实现对其的自动配置 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
</dependencies>

</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package cn.iocoder.springcloud.labx23.hystrixdemo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.hystrix.dashboard.EnableHystrixDashboard;
import org.springframework.cloud.netflix.turbine.EnableTurbine;

@SpringBootApplication
@EnableHystrixDashboard
@EnableTurbine
public class HystrixDashboardApplication {

public static void main(String[] args) {
SpringApplication.run(HystrixDashboardApplication.class, args);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
server:
port: 9090

spring:
application:
name: hystrix-dashboard

eureka:
client:
service-url:
defaultZone: http://127.0.0.1:8761/eureka/ # Eureka-Server 地址

turbine:
app-config: hystrix-demo
combine-host-port: true
cluster-name-expression: new String('default')
70 changes: 70 additions & 0 deletions labx-23/labx-23-scn-hystrix-demo01-cluster/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
<?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">
<parent>
<artifactId>labx-23</artifactId>
<groupId>cn.iocoder.springboot.labs</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

<artifactId>labx-23-scn-hystrix-demo01-cluster</artifactId>

<properties>
<maven.compiler.target>1.8</maven.compiler.target>
<maven.compiler.source>1.8</maven.compiler.source>
<spring.boot.version>2.2.4.RELEASE</spring.boot.version>
<spring.cloud.version>Hoxton.SR1</spring.cloud.version>
</properties>

<!--
引入 Spring Boot、Spring Cloud、Spring Cloud Alibaba 三者 BOM 文件,进行依赖版本的管理,防止不兼容。
在 https://dwz.cn/mcLIfNKt 文章中,Spring Cloud Alibaba 开发团队推荐了三者的依赖关系
-->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>${spring.boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring.cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>

<dependencies>
<!-- 引入 SpringMVC 相关依赖,并实现对其的自动配置 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>

<!-- 引入 Spring Cloud Netflix Hystrix 相关依赖,将 Hystrix 作为服务保障组件,并实现对其的自动配置 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>

<!-- 实现对 Actuator 的自动化配置 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

<!-- 引入 Spring Cloud Netflix Eureka Client 相关依赖,将 Eureka 作为注册中心的客户端,并实现对其的自动配置 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
</dependencies>

</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package cn.iocoder.springcloud.labx23.hystrixdemo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;

@SpringBootApplication
@EnableCircuitBreaker // 声明开启断路器
public class DemoApplication {

@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}

public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package cn.iocoder.springcloud.labx23.hystrixdemo.controller;

import cn.iocoder.springcloud.labx23.hystrixdemo.service.CacheDemoService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/cache-demo")
public class CacheDemoController {

@Autowired
private CacheDemoService cacheDemoService;

@GetMapping("/get_user")
public String getUser(@RequestParam("id") Integer id) {
String userA = cacheDemoService.getUser(id);
String userB = cacheDemoService.getUser(id);
String userC = cacheDemoService.getUser(id);
return userC;
}

@GetMapping("/update_user")
public String updateUser(@RequestParam("id") Integer id) {
String userA = cacheDemoService.getUser(id);
cacheDemoService.updateUser(id);
String userC = cacheDemoService.getUser(id);
return userC;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package cn.iocoder.springcloud.labx23.hystrixdemo.controller;

import cn.iocoder.springcloud.labx23.hystrixdemo.service.CollapserDemoService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;

@RestController
@RequestMapping("/collapser-demo")
public class CollapserDemoController {

private Logger logger = LoggerFactory.getLogger(CollapserDemoController.class);

@Autowired
private CollapserDemoService collapserDemoService;

@GetMapping("/test")
public void test() throws ExecutionException, InterruptedException {
logger.info("[test][准备获取用户信息]");
Future<String> user01 = collapserDemoService.getUserFuture(1);
Future<String> user02 = collapserDemoService.getUserFuture(2);
logger.info("[test][提交获取用户信息]");

logger.info("[test][user({}) 的结果为({})]", 1, user01.get());
logger.info("[test][user({}) 的结果为({})]", 2, user02.get());
}


@GetMapping("/test_02")
public void test02() throws ExecutionException, InterruptedException {
logger.info("[test][准备获取用户信息]");
Future<String> user01 = collapserDemoService.getUserFuture(2);
Future<String> user02 = collapserDemoService.getUserFuture(1);
logger.info("[test][提交获取用户信息]");

logger.info("[test][user({}) 的结果为({})]", 1, user01.get());
logger.info("[test][user({}) 的结果为({})]", 2, user02.get());
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package cn.iocoder.springcloud.labx23.hystrixdemo.controller;

import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import org.apache.commons.lang.exception.ExceptionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

@RestController
@RequestMapping("/demo")
public class DemoController {

private Logger logger = LoggerFactory.getLogger(getClass());

@Autowired
private RestTemplate restTemplate;

@GetMapping("/get_user")
@HystrixCommand(fallbackMethod = "getUserFallback")
public String getUser(@RequestParam("id") Integer id) {
logger.info("[getUser][准备调用 user-service 获取用户({})详情]", id);
return restTemplate.getForEntity("http://127.0.0.1:18080/user/get?id=" + id, String.class).getBody();
}

public String getUserFallback(Integer id, Throwable throwable) {
logger.info("[getUserFallback][id({}) exception({})]", id, ExceptionUtils.getRootCauseMessage(throwable));
return "mock:User:" + id;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package cn.iocoder.springcloud.labx23.hystrixdemo.filter;

import com.netflix.hystrix.strategy.concurrency.HystrixRequestContext;
import org.springframework.stereotype.Component;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;

@Component
@WebFilter(urlPatterns = "/")
public class HystrixRequestContextFilter implements Filter {

@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
// 初始化 HystrixRequestContext
HystrixRequestContext context = HystrixRequestContext.initializeContext();
// 继续过滤器
try {
chain.doFilter(request, response);
} finally {
// 销毁 HystrixRequestContext
context.close();
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package cn.iocoder.springcloud.labx23.hystrixdemo.service;

import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.cache.annotation.CacheRemove;
import com.netflix.hystrix.contrib.javanica.cache.annotation.CacheResult;
import org.apache.commons.lang.exception.ExceptionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

@Service
public class CacheDemoService {

private Logger logger = LoggerFactory.getLogger(CacheDemoService.class);

@Autowired
private RestTemplate restTemplate;

@HystrixCommand(fallbackMethod = "getUserFallback")
@CacheResult(cacheKeyMethod = "genGetUserCacheKey")
public String getUser(Integer id) {
logger.info("[getUser][准备调用 user-service 获取用户({})详情]", id);
return restTemplate.getForEntity("http://127.0.0.1:18080/user/get?id=" + id, String.class).getBody();
}

@HystrixCommand
@CacheRemove(commandKey = "getUser", cacheKeyMethod = "genGetUserCacheKey")
public void updateUser(Integer id) {
logger.info("[updateUser][更新用户({})详情]", id);
}

public String getUserFallback(Integer id, Throwable throwable) {
logger.info("[getUserFallback][id({}) exception({})]", id, ExceptionUtils.getRootCauseMessage(throwable));
return "mock:User:" + id;
}

public String genGetUserCacheKey(Integer id) {
return "USER_" + id;
}

}
Loading

0 comments on commit 8aeb88f

Please sign in to comment.