1.1 服务雪崩简介,解决





雪崩解决:



服务降级
serivce
package com.agan.eureka.consumer.service;
import java.util.ArrayList;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import com.agan.eureka.consumer.domain.Product;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
import com.netflix.hystrix.contrib.javanica.conf.HystrixPropertiesManager;
/\*\*
\* @author 阿甘 http://study.163.com/instructor/1016671292.htm
\* @version 1.0
\*/
@Service
public class ProductService {
@Autowired
private LoadBalancerClient loadBalancerClient;//ribbon 负载均衡客户端
@HystrixCommand(fallbackMethod = "fallback",
commandProperties = {
//默认10秒;如果并发数达到该设置值,请求会被拒绝和抛出异常并且fallback不会被调用。
@HystrixProperty(name=HystrixPropertiesManager.FALLBACK\_ISOLATION\_SEMAPHORE\_MAX\_CONCURRENT\_REQUESTS, value="15")
})
public List<Product> listProduct(){
ServiceInstance si=loadBalancerClient.choose("e-book-product");
StringBuffer sb=new StringBuffer("");
sb.append("http://");
sb.append(si.getHost());
sb.append(":");
sb.append(si.getPort());
sb.append("/product/list");
System.out.println(sb.toString());
RestTemplate rt=new RestTemplate();
ParameterizedTypeReference<List<Product>> typeRef
=new ParameterizedTypeReference<List<Product>>(){};
ResponseEntity<List<Product>> resp=rt.exchange(sb.toString(), HttpMethod.GET, null, typeRef) ;
List<Product> plist=resp.getBody();
return plist;
}
public List<Product> fallback(){
List<Product> list=new ArrayList<Product>();
list.add(new Product(-1,"fallback"));
return list;
}
}
启动类
package com.agan.eureka.consumer;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
/\*\*
\* @author 阿甘 http://study.163.com/instructor/1016671292.htm
\* @version 1.0
\*/
@EnableCircuitBreaker //开启服务降级 断路器
@EnableEurekaClient
@SpringBootApplication
public class ConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(ConsumerApplication.class, args);
}
}
1.1.1 重要补充

达到最大并发度不会调fallback
(1)方法抛出非HystrixBadRequestException:请求参数错误
1.1 请求缓存:e-book-consumer-hystrix-ribbon-cache
hystrix缺点:
仅支持本地缓存
不支持集群,缓存无法同步
不支持第三方缓存容器(redis)
改用spring cache
springcache
spring.application.name=e-book-consumer-hystrix
server.port=9000
eureka.client.serviceUrl.defaultZone=http://user:123456@eureka1:8761/eureka/,http://user:123456@eureka2:8761/eureka/
#默认是hostname 注册,改成IP 注册
eureka.instance.perferIpAddress=true
#程序启动时创建的缓存名称
#spring.cache.cache-names=com.agan.book
# Redis数据索引(默认为0)
spring.redis.database=1
#Redis服务器地址
spring.redis.host=192.168.48.38
#Redis服务器连接端口
spring.redis.port=6379
#Redis服务器连接密码(默认为空)
spring.redis.password=
#连接池最大连接数(负值表示没有限制)
spring.redis.pool.max-active=100
#连接池最大阻塞等待时间(负值表示没有限制)
spring.redis.pool.max-wait=3000
#连接池最大空闭连接数
spring.redis.pool.max-idle=200
#连接汉最小空闲连接数
spring.redis.pool.min-idle=50
#连接超时时间(毫秒)
spring.redis.pool.timeout=600
service层
package com.agan.eureka.consumer.service;
import java.util.ArrayList;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import com.agan.eureka.consumer.domain.Product;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
import com.netflix.hystrix.contrib.javanica.conf.HystrixPropertiesManager;
/\*\*
\* @author 阿甘 http://study.163.com/instructor/1016671292.htm
\* @version 1.0
\*/
@CacheConfig(cacheNames={"com.agan.book"})
@Service
public class ProductService {
@Autowired
private LoadBalancerClient loadBalancerClient;//ribbon 负载均衡客户端
@HystrixCommand(fallbackMethod = "fallback",
commandProperties = {
//默认10秒;如果并发数达到该设置值,请求会被拒绝和抛出异常并且fallback不会被调用。
@HystrixProperty(name=HystrixPropertiesManager.FALLBACK\_ISOLATION\_SEMAPHORE\_MAX\_CONCURRENT\_REQUESTS, value="15")
})
public List<Product> listProduct(){
ServiceInstance si=loadBalancerClient.choose("e-book-product");
StringBuffer sb=new StringBuffer("");
sb.append("http://");
sb.append(si.getHost());
sb.append(":");
sb.append(si.getPort());
sb.append("/product/list");
System.out.println(sb.toString());
RestTemplate rt=new RestTemplate();
ParameterizedTypeReference<List<Product>> typeRef
=new ParameterizedTypeReference<List<Product>>(){};
ResponseEntity<List<Product>> resp=rt.exchange(sb.toString(), HttpMethod.GET, null, typeRef) ;
List<Product> plist=resp.getBody();
return plist;
}
public List<Product> fallback(){
List<Product> list=new ArrayList<Product>();
list.add(new Product(-1,"fallback"));
return list;
}
@Cacheable(key="'product' + #id")
public Product get(Integer id){
System.out.println("=========get========="+id);
return new Product(id,"漫谈spring cloud分布式服务架构(微服务进阶篇)");
}
@CacheEvict(key="'product' + #id")
public void del(Integer id){
System.out.println("=========del========="+id);
}
}
启动类
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
@EnableCaching
@EnableCircuitBreaker //开启服务降级 断路器
@EnableEurekaClient
@SpringBootApplication
public class ConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(ConsumerApplication.class, args);
}
}
1.1.1 重要参数

请求合并:



业务层
package com.agan.eureka.consumer.service;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Future;
import org.springframework.stereotype.Service;
import com.agan.eureka.consumer.domain.Product;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCollapser;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
/\*\*
\* @author 阿甘 http://study.163.com/instructor/1016671292.htm
\* @version 1.0
\*/
@Service
public class ProductService {
//利用hystrix合并请求
@HystrixCollapser(batchMethod = "batchProduct", scope = com.netflix.hystrix.HystrixCollapser.Scope.GLOBAL,
collapserProperties = {
//请求时间间隔在50ms之内的请求会被合并为一个请求
@HystrixProperty(name = "timerDelayInMilliseconds", value = "20"),
//设置触发批处理执行之前,在批处理中允许的最大请求数。
@HystrixProperty(name = "maxRequestsInBatch", value = "200"),
})
public **Future**<Product> getProduct(Integer id){
System.out.println("------------"+id+"-------------");
return null;
}
@HystrixCommand
public List<Product> batchProduct(List<Integer> ids){
for(Integer id:ids){
System.out.println(id);
}
List<Product> list=new ArrayList<Product>();
list.add(new Product(1,"漫谈spring cloud与spring boot基础架构(微服务基础篇)"));
list.add(new Product(2,"漫谈spring cloud分布式服务架构(微服务进阶篇)"));
list.add(new Product(3,"漫谈spring cloud 与docker架构部署(微服务高级篇)"));
list.add(new Product(4,"444444444444444444"));
return list;
}
}****
启动类
package com.agan.eureka.consumer;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
@EnableCircuitBreaker //开启服务降级 断路器
@EnableEurekaClient
@SpringBootApplication
public class ConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(ConsumerApplication.class, args);
}
}
效果

1.1 服务熔断:e-book-consumer-hystrix-ribbon-breaker


业务层
package com.agan.eureka.consumer.service;
import java.util.ArrayList;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import com.agan.eureka.consumer.domain.Product;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
import com.netflix.hystrix.contrib.javanica.conf.HystrixPropertiesManager;
/\*\*
\* @author 阿甘 http://study.163.com/instructor/1016671292.htm
\* @version 1.0
\*/
@Service
public class ProductService {
@Autowired
private LoadBalancerClient loadBalancerClient;//ribbon 负载均衡客户端
@HystrixCommand(fallbackMethod = "fallback",
commandProperties = {
//默认20个;10s内请求数大于20个时就启动熔断器,当请求符合熔断条件时将触发getFallback()。
@HystrixProperty(name=HystrixPropertiesManager.CIRCUIT\_BREAKER\_REQUEST\_VOLUME\_THRESHOLD, value="10"),
//请求错误率大于50%时就熔断,然后for循环发起请求,当请求符合熔断条件时将触发getFallback()。
@HystrixProperty(name=HystrixPropertiesManager.CIRCUIT\_BREAKER\_ERROR\_THRESHOLD\_PERCENTAGE, value="50"),
//默认5秒;熔断多少秒后去尝试请求
@HystrixProperty(name=HystrixPropertiesManager.CIRCUIT\_BREAKER\_SLEEP\_WINDOW\_IN\_MILLISECONDS, value="5000"),
})
public List<Product> listProduct(int n){
System.out.println(n);
if(n==1){
throw new RuntimeException();
}
ServiceInstance si=loadBalancerClient.choose("e-book-product");
StringBuffer sb=new StringBuffer("");
sb.append("http://");
sb.append(si.getHost());
sb.append(":");
sb.append(si.getPort());
sb.append("/product/list");
System.out.println(sb.toString());
RestTemplate rt=new RestTemplate();
ParameterizedTypeReference<List<Product>> typeRef
=new ParameterizedTypeReference<List<Product>>(){};
ResponseEntity<List<Product>> resp=rt.exchange(sb.toString(), HttpMethod.GET, null, typeRef) ;
List<Product> plist=resp.getBody();
return plist;
}
public List<Product> fallback(int n){
List<Product> list=new ArrayList<Product>();
list.add(new Product(-1,"fallback"));
return list;
}
启动类
package com.agan.eureka.consumer;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
@EnableCircuitBreaker //开启服务降级 断路器
@EnableEurekaClient
@SpringBootApplication
public class ConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(ConsumerApplication.class, args);
}
}
1.1.1 模拟错误率
v

一直刷新页面,也不会打印1,说明5秒内不再重试,每5秒一次

线程池隔离
不使用线程池隔离会互相影响
v


使用线程池隔离,互不影响



业务层
package com.agan.eureka.consumer.service;
import java.util.ArrayList;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import com.agan.eureka.consumer.domain.Product;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
import com.netflix.hystrix.contrib.javanica.conf.HystrixPropertiesManager;
/\*\*
\* @author 阿甘
\*/
@Service
public class ProductService {
@Autowired
private LoadBalancerClient loadBalancerClient;
//ribbon 负载均衡客户端
@HystrixCommand(groupKey="e-book-product", commandKey = "listProduct",
threadPoolKey="e-book-product",
threadPoolProperties = {
@HystrixProperty(name = "coreSize", value = "30"),//线程池大小
@HystrixProperty(name = "maxQueueSize", value = "100"),//最大队列长度
@HystrixProperty(name = "keepAliveTimeMinutes", value = "2"),//线程存活时间
@HystrixProperty(name = "queueSizeRejectionThreshold", value = "15")//拒绝请求
},
fallbackMethod = "fallback")
public List<Product> listProduct(){
ServiceInstance si=loadBalancerClient.choose("e-book-product");
StringBuffer sb=new StringBuffer("");
sb.append("http://");
sb.append(si.getHost());
sb.append(":");
sb.append(si.getPort());
sb.append("/product/list");
System.out.println(sb.toString());
RestTemplate rt=new RestTemplate();
ParameterizedTypeReference<List<Product>> typeRef
=new ParameterizedTypeReference<List<Product>>(){};
ResponseEntity<List<Product>> resp=rt.exchange(sb.toString(), HttpMethod.GET, null, typeRef) ;
List<Product> plist=resp.getBody();
return plist;
}
public List<Product> fallback(){
List<Product> list=new ArrayList<Product>();
list.add(new Product(-1,"fallback"));
return list;
}
}
启动类
package com.agan.eureka.consumer;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.hystrix.EnableHystrix;
import org.springframework.cloud.netflix.hystrix.dashboard.EnableHystrixDashboard;
/\*\*
\* @author 阿甘 http://study.163.com/instructor/1016671292.htm
\* @version 1.0
\*/
@EnableCircuitBreaker //开启服务降级 断路器
@EnableEurekaClient
@SpringBootApplication
@EnableHystrix
@EnableHystrixDashboard
public class ConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(ConsumerApplication.class, args);
}
}
1.1 信号量隔离:e-book-consumer-hystrix-ribbon-semaphore


package com.agan.eureka.consumer.service;
import java.util.ArrayList;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import com.agan.eureka.consumer.domain.Product;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
import com.netflix.hystrix.contrib.javanica.conf.HystrixPropertiesManager;
/\*\*
\* @author 阿甘 http://study.163.com/instructor/1016671292.htm
\* @version 1.0
\*/
@Service
public class ProductService {
@Autowired //ribbon 负载均衡客户端
private LoadBalancerClient loadBalancerClient;
@HystrixCommand(fallbackMethod = "fallback",
commandProperties = {
@HystrixProperty(name=HystrixPropertiesManager.EXECUTION\_ISOLATION\_STRATEGY, value="SEMAPHORE"),// 信号量 隔离
@HystrixProperty(name=HystrixPropertiesManager.EXECUTION\_ISOLATION\_SEMAPHORE\_MAX\_CONCURRENT\_REQUESTS, value="100")//信号量最大并发度
})
public List<Product> listProduct(){
ServiceInstance si=loadBalancerClient.choose("e-book-product");
StringBuffer sb=new StringBuffer("");
sb.append("http://");
sb.append(si.getHost());
sb.append(":");
sb.append(si.getPort());
sb.append("/product/list");
System.out.println(sb.toString());
RestTemplate rt=new RestTemplate();
ParameterizedTypeReference<List<Product>> typeRef
=new ParameterizedTypeReference<List<Product>>(){};
ResponseEntity<List<Product>> resp=rt.exchange(sb.toString(), HttpMethod.GET, null, typeRef) ;
List<Product> plist=resp.getBody();
return plist;
}
public List<Product> fallback(){
List<Product> list=new ArrayList<Product>();
list.add(new Product(-1,"fallback"));
return list;
}
}
1.1 线程池隔离和信号量隔离区别,使用场景


Feign服务降级:
spring.application.name=e-book-consumer-hystrix-feign-fallback
server.port=8090
eureka.client.serviceUrl.defaultZone=http://user:123456@eureka1:8761/eureka/,http://user:123456@eureka2:8761/eureka/
#默认是hostname 注册,改成IP 注册
eureka.instance.perferIpAddress=true
#Feign默认是不开启Hystrix
feign.hystrix.enabled=true
业务层
package com.agan.book.consumer.service;
import java.util.List;
import org.springframework.cloud.netflix.feign.FeignClient;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import com.agan.book.consumer.hystrix.ProductServiceFallback;
import com.agan.book.product.domain.Product;
import com.agan.book.product.facade.ProductFacade;
/\*\*
\* @author 阿甘
\* @see http://study.163.com/instructor/1016671292.htm
\* @version 1.0
\*/
@FeignClient(name="e-book-product",fallback=ProductServiceFallback.class)
public interface ProductService {
@RequestMapping(value="product/list",method=RequestMethod.GET)
public List<Product> listProduct();
}
1.1.1 hystrix:ProductServiceFallback
package com.agan.book.consumer.hystrix;
import java.util.ArrayList;
import java.util.List;
import org.springframework.stereotype.Component;
import com.agan.book.consumer.service.ProductService;
import com.agan.book.product.domain.Product;
@Component
public class ProductServiceFallback implements ProductService{
@Override
public List<Product> listProduct() {
List<Product> list=new ArrayList<Product>();
list.add(new Product(-1,"fallback"));
return list;
}
}
测试效果

服务降级本身就是在消费者客户端配置的,所以本案例业务层没有继承facade包下生产者的api
1.1 Feign降级后异常记录:e-book-consumer-hystrix-feign-factory
在fallback类中输出日志就可以了
package com.agan.book.consumer.hystrix;
import java.util.ArrayList;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import com.agan.book.consumer.service.ProductService;
import com.agan.book.product.domain.Product;
import feign.hystrix.FallbackFactory;
@Component
public class ProductServiceFallbackFactory implements FallbackFactory<ProductService>{
private Logger logger=LoggerFactory.getLogger(ProductServiceFallbackFactory.class);
@Override
public ProductService create(final Throwable arg0) {
return new ProductService(){
@Override
public List<Product> listProduct() {
logger.warn("fallback exception:",arg0);
List<Product> list=new ArrayList<Product>();
list.add(new Product(-1,"fallback"));
return list;
}
};
}
}
1.1 可视化数据监控dashboard:e-book-consumer-hystrix-dashboard
pom
<?xml version="1.0"?>
<project
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.agan.springcloud</groupId>
<artifactId>e-book-consumer-hystrix</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>e-book-consumer-hystrix-dashboard</artifactId>
<name>eureka-consumer</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix-dashboard</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
1.1.1 Resource:application.properties和logback.xml
spring.application.name=e-book-hystrix-dashboard
server.port=1001
eureka.client.serviceUrl.defaultZone=http://user:123456@eureka1:8761/eureka/,http://user:123456@eureka2:8761/eureka/
#默认是hostname 注册,改成IP 注册
eureka.instance.perferIpAddress=true
1.1.1 启动类
package com.agan.hystrix;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.hystrix.EnableHystrix;
import org.springframework.cloud.netflix.hystrix.dashboard.EnableHystrixDashboard;
@EnableCircuitBreaker //开启服务降级 断路器
@EnableEurekaClient
@SpringBootApplication
@EnableHystrix
@EnableHystrixDashboard
public class HystrixDashboardApplication {
public static void main(String[] args) {
SpringApplication.run(HystrixDashboardApplication.class, args);
}
}
1.1.1 测试,启动8.6——ribbon-thhredpool


启动本项目

不断刷新页面可看到变化

1.1.1 图解

1.1 集群监控数据:e-book-consumer-hystrix-turbine

1.1.1 pom.xml
<?xml version="1.0"?>
<project
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.agan.springcloud</groupId>
<artifactId>e-book-consumer-hystrix</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>e-book-consumer-hystrix-turbine</artifactId>
<name>eureka-consumer</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix-dashboard</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-turbine</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-netflix-turbine</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
1.1.1 Resource:application.properties和logback.xml
spring.application.name=e-book-hystrix-dashboard
server.port=1002
eureka.client.serviceUrl.defaultZone=http://user:123456@eureka1:8761/eureka/,http://user:123456@eureka2:8761/eureka/
#默认是hostname 注册,改成IP 注册
eureka.instance.perferIpAddress=true
#---------------------------------------turbine--------------------------
#配置Eureka中的serviceId列表,表明监控哪些服务
turbine.appConfig=
e-book-consumer-hystrix-ribbon-threadpool,
e-book-consumer-hystrix-feign-fallback
#指定聚合哪些集群,多个使用","分割,默认为default。可使用http://.../turbine.stream?cluster={clusterConfig之一}访问
turbine.aggregator.clusterConfig= default
# 1. clusterNameExpression指定集群名称,默认表达式appName;此时:turbine.aggregator.clusterConfig需要配置想要监控的应用名称;
# 2. 当clusterNameExpression: default时,turbine.aggregator.clusterConfig可以不写,因为默认就是default;
# 3. 当clusterNameExpression: metadata['cluster']时,假设想要监控的应用配置了eureka.instance.metadata-map.cluster: ABC,
# 则需要配置,同时turbine.aggregator.clusterConfig: ABC
turbine.clusterNameExpression="default"
1.1.1 启动类
package com.agan.hystrix;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.hystrix.EnableHystrix;
import org.springframework.cloud.netflix.hystrix.dashboard.EnableHystrixDashboard;
import org.springframework.cloud.netflix.turbine.EnableTurbine;
/\*\*
\* @author 阿甘 http://study.163.com/instructor/1016671292.htm
\* @version 1.0
\*/
@SpringBootApplication
@EnableTurbine
public class HystrixTurbineApplication {
public static void main(String[] args) {
SpringApplication.run(HystrixTurbineApplication.class, args);
}
}
1.1.1 启动7.2生产者,8.12——turbine,8.11-dashboard
1.1.1 启动8.9——feign-fallback

测试效果


1.1.1 启动8.6——ribbon-threadpool


1.1.1 测试



1.1.1 Linux另外启动8.6——ribbon-threadpool


1.1.1 测试效果

不使用turbine,需要一个个生产者-消费者添加,数据是独立的,不能整合到一块,
上图我们可以看到,ribbon-threadpool集群有俩消费者,数据在一起,
feign-fallback只有一个消费者,单独
1.1 RabbitMQ收集监控数据:

1.1.1 e-book-consumer-hystrix-ribbon-threadpool-mq
1.1.1.1 pom.xml
<?xml version="1.0"?>
<project
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.agan.springcloud</groupId>
<artifactId>e-book-consumer-hystrix</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>e-book-consumer-hystrix-ribbon-threadpool-mq</artifactId>
<name>eureka-consumer</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix-dashboard</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-netflix-hystrix-stream</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-stream-rabbit</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
1.1.1.1 Resource:application.properties和logback.xml
spring.application.name=e-book-consumer-hystrix-ribbon-threadpool
server.port=9000
eureka.client.serviceUrl.defaultZone=http://user:123456@eureka1:8761/eureka/,http://user:123456@eureka2:8761/eureka/
#默认是hostname 注册,改成IP 注册
eureka.instance.perferIpAddress=true
spring.rabbitmq.host=192.168.10.17
spring.rabbitmq.port=5672
spring.rabbitmq.username=test
spring.rabbitmq.password=123456
spring.rabbitmq.virtualHost=/
1.1.1.1 控制层ProductController
package com.agan.eureka.consumer.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import com.agan.eureka.consumer.domain.Product;
import com.agan.eureka.consumer.service.ProductService;
/\*\*
\* @author 阿甘 http://study.163.com/instructor/1016671292.htm
\* @version 1.0
\*/
@RestController
public class ProductController {
@Autowired
private ProductService productService;
@RequestMapping(value = "list", method = RequestMethod.GET)
public List<Product> listProduct() {
List<Product> list = this.productService.listProduct();
return list;
}
}
1.1.1.1 业务层ProductService