参考 英文原文:https://stackabuse.com/spring-cloud-turbine/ 中文版:https://www.jb51.net/article/162726.htm
<?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>com.cntaiping.tpa</groupId>
<artifactId>turbine</artifactId>
<packaging>pom</packaging>
<version>1.0-SNAPSHOT</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<spring-cloud.version>Greenwich.SR1</spring-cloud.version>
</properties>
<!--配置继承spring-boot-starter-parent-->
<!--
Spring Boot的每个发布版本都会规划它所支持的依赖项
spring-boot-starter-parent项目,来获取最佳依赖
只需要在这里指定Spring Boot的版本号。如果导入其他的starters,你可以完全省略版本号。-->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.5.RELEASE</version>
<relativePath/>
</parent>
<modules>
<module>eureka-server</module>
<module>user-service</module>
<module>recommend-service</module>
<module>hystrix-turbine</module>
</modules>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<!--
spring-cloud-dependencies也是一个依赖管理器的pom文件,与spring-boot-starter-parent的作用一样,
不同的是spring-cloud-dependencies是对cloud的依赖管理。
-->
<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>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
(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>com.cntaiping.tpa</groupId>
<artifactId>eureka-server</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>eureka-server</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>com.cntaiping.tpa</groupId>
<artifactId>turbine</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
</dependencies>
</project>
(2) application.properties
server.port= 8761
eureka.client.registerWithEureka= false
eureka.client.fetchRegistry= false
eureka.server.waitTimeInMsWhenSyncEmpty= 0
(3)Appliaction类
package com.cntaiping.tpa.eurekaserver;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaServerApplication.class, args);
}
}
(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>com.cntaiping.tpa</groupId>
<artifactId>recommend-service</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>recommend-service</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>com.cntaiping.tpa</groupId>
<artifactId>turbine</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
</dependencies>
</project>
(2)application.properties
server.port= 7070
spring.application.name= recommend-service
eureka.client.serviceUrl.defaultZone= http://localhost:8761/eureka/
management.endpoints.web.exposure.include=*
(3)Appliaction类
package com.cntaiping.tpa.recommendservice;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@SpringBootApplication
@EnableDiscoveryClient
@EnableCircuitBreaker
public class RecommendServiceApplication {
public static void main(String[] args) {
SpringApplication.run(RecommendServiceApplication.class, args);
}
}
(4)控制器
package com.cntaiping.tpa.recommendservice.controller;
import com.cntaiping.tpa.recommendservice.bean.ProductBean;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import java.util.*;
@RestController
public class RecommendController {
@RequestMapping(value = "/recommend", method = RequestMethod.GET)
@HystrixCommand(fallbackMethod = "recommendFallback")
@ResponseBody
public List<ProductBean> recommend() {
List<ProductBean> products = new ArrayList<ProductBean>();
products.add(new ProductBean("Product1", "Description1", "link1"));
products.add(new ProductBean("Product2", "Description2", "link3"));
products.add(new ProductBean("Product3", "Description3", "link3"));
return products;
}
public List<ProductBean> recommendFallback() {
System.out.println("=======recommendationFallback=========");
return new ArrayList<ProductBean>();
}
}
(5)bean
package com.cntaiping.tpa.recommendservice.bean;
public class ProductBean {
private String name;
private String description;
private String detailsLink;
public ProductBean(String name, String description, String detailsLink) {
super();
this.name = name;
this.description = description;
this.detailsLink = detailsLink;
}
public ProductBean() {
// TODO Auto-generated constructor stub
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getDetailsLink() {
return detailsLink;
}
public void setDetailsLink(String detailsLink) {
this.detailsLink = detailsLink;
}
}
(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>com.cntaiping.tpa</groupId>
<artifactId>user-service</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>user-service</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>com.cntaiping.tpa</groupId>
<artifactId>turbine</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
</dependencies>
</project>
(2)application.properties
server.port= 7060
spring.application.name= user-service
eureka.client.serviceUrl.defaultZone= http://localhost:8761/eureka/
management.endpoints.web.exposure.include=*
(3)Appliaction类
package com.cntaiping.tpa.userservice;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
@SpringBootApplication
@EnableDiscoveryClient
@EnableCircuitBreaker
public class UserServiceApplication {
public static void main(String[] args) {
SpringApplication.run(UserServiceApplication.class, args);
}
@LoadBalanced
@Bean
RestTemplate restTemplate() {
return new RestTemplate();
}
}
(4)控制器
package com.cntaiping.tpa.userservice.controller;
import com.cntaiping.tpa.userservice.bean.ProductBean;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
@RestController
public class UserController {
@Autowired
RestTemplate restTemplate;
@GetMapping(value = "/personalized/{id}")
@HystrixCommand(fallbackMethod = "recommendFallback")
public ProductBean[] personalized(@PathVariable int id) {
ProductBean[] result = restTemplate.getForObject("http://recommend-service/recommend", ProductBean[].class);
return result;
}
public ProductBean[] recommendFallback(int id) {
System.out.println("=======recommendFallback=========" + id);
return new ProductBean[0];
}
}
(5)bean
public class ProductBean {
private String name;
private String description;
private String detailsLink;
public ProductBean(String name, String description, String detailsLink) {
super();
this.name = name;
this.description = description;
this.detailsLink = detailsLink;
}
...
}
(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>com.cntaiping.tpa</groupId>
<artifactId>hystrix-turbine</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>hystrix-turbine</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>com.cntaiping.tpa</groupId>
<artifactId>turbine</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<dependencies>
<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>
</dependencies>
</project>
(2)application.properties
server.port= 7090
spring.application.name= hystirx-turbine
eureka.client.serviceUrl.defaultZone= http://localhost:8761/eureka/
turbine.appConfig= user-service,recommend-service
turbine.clusterNameExpression= new String("default")
(3)Application类
package com.cntaiping.tpa.hystrixturbine;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.hystrix.dashboard.EnableHystrixDashboard;
import org.springframework.cloud.netflix.turbine.EnableTurbine;
@SpringBootApplication
@EnableTurbine
@EnableDiscoveryClient
@EnableHystrixDashboard
public class HystrixTurbineApplication {
public static void main(String[] args) {
SpringApplication.run(HystrixTurbineApplication.class, args);
}
}
其中Eureka Server运行效果如下图
http://localhost:7060/personalized/1
user-service和recommend-service都实现了Hystrix回退机制,并通过Actuator暴露了/hystrix.stream端点:
用户服务的Hystrix端点:http://localhost:7060/actuator/hystrix.stream
用于推荐服务的Hystrix端点:http://localhost:7070/actuator/hystrix.stream
输入:http://localhost:7060/actuator/hystrix.stream
Turbine可以将所有单独的hystrix.stream聚合成一个turbine.stream,以便在Hystrix Dashboard上查看
我们可以打开http://localhost:7090/turbine.stream?cluster=default来查看user-service和recommend-service的聚合流: