學習SpringCloud Hystrix帶你從0到1
一、什麼是災難性的雪崩效應
1.出現雪崩現象的過程
正常情況下請求經過多個服務傳到服務T,服務T進行處理並逐級返回。
當服務B接收到了大量的請求時,最終處理服務的服務T會受到壓力,導致服務崩掉。
因為服務T最先癱瘓,請求就會積壓在服務U,當壓力過大時各級系統都會崩掉,這樣就令這條線路的服務全部不可用了。
一個線路的癱瘓也會影響到其他線路,這樣整個系統就會崩掉了
2.造成雪崩的原因
- 服務提供者不可用(硬體故障、程式bug、快取擊穿、使用者大量請求)
- 重試加大流量(使用者重試、程式碼邏輯重試)
- 服務呼叫者不可用(同步等待造成的資源耗盡)
最終的結果就是一個服務不可用,連帶著多個服務都不可用,最終導致系統全面癱瘓。
二、如何解決災難性雪崩效應
-
降級
超時降級、資源不足時(執行緒或訊號量)降級,降級後可以配合降級介面返回託底資料。
實現一個fallback方法,當請求後端服務出現異常的時候,可以使用fallback方法返回值。
-
隔離(執行緒池隔離和訊號量隔離)
限制呼叫分散式服務的資源使用,某一個呼叫的服務出現問題不會影響其他服務呼叫。
-
熔斷
當失敗率(網路故障、超時造成的失敗率)達到閾值自動觸發降級,熔斷器觸發的快速失敗會進行快速恢復
-
快取
提供了請求快取
-
請求合併
提供請求合併
1.降級
對服務做降級處理
1.1 建立專案
1.2 新增座標
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency>
複製程式碼
1.3 修改配置檔案
spring.application.name=eureka-consumer-ribbon-hystrix
server.port=9010
#設定服務註冊中心地址,向所有註冊中心做註冊
eureka.client.serviceUrl.defaultZone=http://user:123456@eureka1:8761/eureka/,http://user:123456@eureka2:8761/eureka/
複製程式碼
1.4 修改啟動類,開啟熔斷器
//開啟熔斷器
@EnableCircuitBreaker
//表示Eureka的客戶端
@EnableEurekaClient
@SpringBootApplication
public class ConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(ConsumerApplication.class,args);
}
}
複製程式碼
1.5 在專案中新增Product實體類
1.6 修改ProductService
@Service
public class ProductService {
@Autowired
private LoadBalancerClient loadBalancerClient; //ribbon:負載均衡器
//開啟服務降級處理,指定返回託底資料的方法
@HystrixCommand(fallbackMethod = "fallback")
public List<Product> getUsers(){
//選擇呼叫的服務的名稱
//ServiceInstance:封裝了服務的基本資訊,如:ip、埠號
ServiceInstance si = loadBalancerClient.choose("ego-product-provider");
//拼接訪問服務的url
StringBuffer sb = new StringBuffer();
//http://localhost:9001/user/product/findAll
sb.append("http://").append(si.getHost()).append(":").append(si.getPort()).append("/product/findAll");
System.out.println(sb.toString());
//SpringMVC RestTemplate
RestTemplate restTemplate = new RestTemplate();
ParameterizedTypeReference<List<Product>> type = new ParameterizedTypeReference<List<Product>>() {
};
//ResponseEntity:封裝了返回值資訊
ResponseEntity<List<Product>> entity = restTemplate.exchange(sb.toString(),HttpMethod.GET,null,type);
return entity.getBody();
}
//返回託底資料的方法
public List<Product> fallback(){
ArrayList<Product> list = new ArrayList<>();
list.add(new Product(-1,"我是託底資料"));
return list;
}
}
複製程式碼
1.7 以下四種情況將觸發getFallback呼叫
- 方法丟擲非 HystrixBadRequestException 異常
- 方法呼叫超時
- 熔斷器開啟攔截呼叫
- 執行緒池佇列訊號量是否跑滿
2.請求快取
Hystrix為了降低訪問服務的頻率,支援將一個請求與返回結果做快取處理,如果再次請求的url沒有變化,那麼hystrix不會請求服務,而是直接從快取中將結果返回,這樣可以大大降低訪問服務的壓力。
Hystrix自帶快取,有以下兩個缺點
1.是一個本地快取,在叢集情況下快取是同步的。
2.不支援第三方快取容器。如:Redis、Memcache
解決:可以使用spring的快取
2.1 安裝Redis
2.2 建立專案
2.3 新增座標
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
複製程式碼
2.4 修改配置檔案
spring.application.name=eureka-consumer-ribbon-cache
server.port=9010
#設定服務註冊中心地址,向所有註冊中心做註冊
eureka.client.serviceUrl.defaultZone=http://user:123456@eureka1:8761/eureka/,http://user:123456@eureka2:8761/eureka/
#Redis
spring.redis.database=0
#redis的伺服器地址
spring.redis.host=192.168.234.129
#redis埠號
spring.redis.port=6379
#最大連線數
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
複製程式碼
2.5 修改啟動類,開啟快取
@EnableCaching
//表示Eureka的客戶端
@EnableEurekaClient
@SpringBootApplication
public class ConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(ConsumerApplication.class,args);
}
}
複製程式碼
2.6 修改ProductService
@Service
//為快取資料設定統一字首
@CacheConfig(cacheNames = {"com.luyi.ego.product"})
public class ProductService {
@Autowired
private LoadBalancerClient loadBalancerClient; //ribbon:負載均衡器
//開啟服務降級處理,指定返回託底資料的方法
@HystrixCommand(fallbackMethod = "fallback")
public List<Product> getUsers(){
//選擇呼叫的服務的名稱
//ServiceInstance:封裝了服務的基本資訊,如:ip、埠號
ServiceInstance si = loadBalancerClient.choose("ego-product-provider");
//拼接訪問服務的url
StringBuffer sb = new StringBuffer();
//http://localhost:9001/user/product/findAll
sb.append("http://").append(si.getHost()).append(":").append(si.getPort()).append("/product/findAll");
System.out.println(sb.toString());
//SpringMVC RestTemplate
RestTemplate restTemplate = new RestTemplate();
ParameterizedTypeReference<List<Product>> type = new ParameterizedTypeReference<List<Product>>() {
};
//ResponseEntity:封裝了返回值資訊
ResponseEntity<List<Product>> entity = restTemplate.exchange(sb.toString(),"我是託底資料"));
return list;
}
//根據id查詢商品
@Cacheable(key = "'product' + #id") //新增id為字尾生成key
public Product getProductById(Integer id){
System.out.println("============Get===========" + id);
return new Product(id,"新的商品");
}
//根據id刪除商品
@CacheEvict(key = "'product' + #id")
public void delProductById(Integer id){
System.out.println("============Del===========" + id);
}
}
複製程式碼
2.7 修改ProductController
@RestController
public class ProductController {
@Autowired
private ProductService userService;
@RequestMapping("/consumer")
public List<Product> getUsers(){
return userService.getUsers();
}
@RequestMapping(value = "/get",method = RequestMethod.GET)
public Product get(Integer id){
return userService.getProductById(id);
}
@RequestMapping(value = "del",method = RequestMethod.GET)
public void del(Integer id){
userService.delProductById(id);
}
}
複製程式碼
3.請求合併
3.1 沒合併的請求與合併的請求
3.2 什麼情況下使用請求合併
在微服務架構中會拆分成多個小的模組,各個模組之間進行呼叫是需要通訊的,但是在併發量大的情況下會令大量執行緒處於等待狀態,這就會增加響應時間,所以可以使用請求合併將多次請求合併為一次請求。
3.3 請求合併的缺點
在設定了請求合併以後,本來一次請求只需要5ms就搞定了,但是使用了請求合併後可能還需要再等待10ms,看看還有沒有其他請求一起,這樣一次請求就從5ms增加到了15ms。不過如果我們發起的命令本來就是一個高延遲的命令,那麼這個時候就可以使用請求合併了,因為這個時候時間窗的時間消耗就顯得微不足道了。高併發也是請求合併的重要場景。
3.4 建立專案
3.5 修改pom檔案,新增hystrix座標
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency>
複製程式碼
3.6 修改配置檔案
spring.application.name=eureka-consumer-ribbon-batch
server.port=9010
#設定服務註冊中心地址,向所有註冊中心做註冊
eureka.client.serviceUrl.defaultZone=http://user:123456@eureka1:8761/eureka/,http://user:123456@eureka2:8761/eureka/
複製程式碼
3.7 修改ProductService
@Service
public class ProductService {
//利用 hystrix 合併請求
@HystrixCollapser(batchMethod = "batchProduct",scope =
com.netflix.hystrix.HystrixCollapser.Scope.GLOBAL,collapserProperties = {
//請求時間間隔在 20ms 之內的請求會被合併為一個請求,預設為 10ms
@HystrixProperty(name =
"timerDelayInMilliseconds",value = "20"),//設定觸發批處理執行之前,在批處理中允許的最大請求數。
@HystrixProperty(name = "maxRequestsInBatch",value = "200"),})
//Consumer的Controller呼叫的方法,該方法返回值必須為Future型別
public Future<Product> getProduct(Integer id) {
System.out.println("==============" + id + "============");
return null;
}
//呼叫Provider服務的方法(假設)
@HystrixCommand
public List<Product> batchProduct(List<Integer> ids) {
for (Integer id : ids) {
System.out.println(id);
}
//假設是呼叫provider服務後返回的list
List<Product> list = new ArrayList<>();
list.add(new Product(1,"電視"));
list.add(new Product(2,"電腦"));
list.add(new Product(3,"冰箱"));
list.add(new Product(4,"手電筒"));
list.add(new Product(100,"list....."));
System.out.println("ddddddddddd");
return list;
}
}
複製程式碼
3.8 修改Controller
@RestController
public class ProductController {
@Autowired
private ProductService userService;
@RequestMapping("/consumer")
public void getUsers() throws ExecutionException,InterruptedException {
Future<Product> p1 = userService.getProduct(1);
Future<Product> p2 = userService.getProduct(2);
Future<Product> p3 = userService.getProduct(3);
System.out.println(p1.get().toString());
System.out.println(p2.get().toString());
System.out.println(p3.get().toString());
}
}
複製程式碼
3.9 請求合併引數介紹
4.服務熔斷
4.1 建立專案
4.2 新增hystrix座標
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency>
複製程式碼
4.3 修改配置檔案
spring.application.name=eureka-consumer-ribbon-breaker
server.port=9010
#設定服務註冊中心地址,向所有註冊中心做註冊
eureka.client.serviceUrl.defaultZone=http://user:123456@eureka1:8761/eureka/,http://user:123456@eureka2:8761/eureka/
複製程式碼
4.4 修改啟動類
//開啟熔斷器
@EnableCircuitBreaker
//表示Eureka的客戶端
@EnableEurekaClient
@SpringBootApplication
public class ConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(ConsumerApplication.class,args);
}
}
複製程式碼
4.5 修改ProductService
@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> getUsers(Integer flag) {
System.out.println(flag);
if (flag == 1){
throw new RuntimeException();
}
//選擇呼叫的服務的名稱
//ServiceInstance:封裝了服務的基本資訊,如:ip、埠號
ServiceInstance si = loadBalancerClient.choose("ego-product-provider");
//拼接訪問服務的url
StringBuffer sb = new StringBuffer();
//http://localhost:9001/user/product/findAll
sb.append("http://").append(si.getHost()).append(":").append(si.getPort()).append("/product/findAll");
System.out.println(sb.toString());
//SpringMVC RestTemplate
RestTemplate restTemplate = new RestTemplate();
ParameterizedTypeReference<List<Product>> type = new ParameterizedTypeReference<List<Product>>() {
};
//ResponseEntity:封裝了返回值資訊
ResponseEntity<List<Product>> entity = restTemplate.exchange(sb.toString(),type);
return entity.getBody();
}
//返回託底資料的方法
public List<Product> fallback(Integer flag) {
ArrayList<Product> list = new ArrayList<>();
list.add(new Product(-1,"我是託底資料"));
return list;
}
}
複製程式碼
4.6 修改ProductController
@RestController
public class ProductController {
@Autowired
private ProductService userService;
@RequestMapping("/consumer")
public List<Product> getUsers(@RequestParam("flag") Integer flag){
return userService.getUsers(flag);
}
}
複製程式碼
4.7 熔斷引數介紹
5.隔離(執行緒池隔離)
5.1 建立專案
5.2 新增座標
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency>
複製程式碼
5.3 修改配置檔案
spring.application.name=eureka-consumer-ribbon-threadpool
server.port=9010
#設定服務註冊中心地址,向所有註冊中心做註冊
eureka.client.serviceUrl.defaultZone=http://user:123456@eureka1:8761/eureka/,http://user:123456@eureka2:8761/eureka/
複製程式碼
5.4 修改啟動類
//開啟熔斷器
@EnableCircuitBreaker
//表示Eureka的客戶端
@EnableEurekaClient
@SpringBootApplication
public class ConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(ConsumerApplication.class,args);
}
}
複製程式碼
5.5 修改ProductService
@Service
public class ProductService {
@Autowired
private LoadBalancerClient loadBalancerClient; //ribbon:負載均衡器
@HystrixCommand(groupKey = "ego-product-provider",commandKey = "getUsers",threadPoolKey = "ego-product-provider",//給執行緒名新增字首
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> getUsers() {
System.out.println(Thread.currentThread().getName());
//選擇呼叫的服務的名稱
//ServiceInstance:封裝了服務的基本資訊,如:ip、埠號
ServiceInstance si = loadBalancerClient.choose("ego-product-provider");
//拼接訪問服務的url
StringBuffer sb = new StringBuffer();
//http://localhost:9001/user/product/findAll
sb.append("http://").append(si.getHost()).append(":").append(si.getPort()).append("/product/findAll");
System.out.println(sb.toString());
//SpringMVC RestTemplate
RestTemplate restTemplate = new RestTemplate();
ParameterizedTypeReference<List<Product>> type = new ParameterizedTypeReference<List<Product>>() {
};
//ResponseEntity:封裝了返回值資訊
ResponseEntity<List<Product>> entity = restTemplate.exchange(sb.toString(),type);
return entity.getBody();
}
//返回託底資料的方法
public List<Product> fallback() {
System.out.println(Thread.currentThread().getName());
ArrayList<Product> list = new ArrayList<>();
list.add(new Product(-1,"我是託底資料"));
return list;
}
public void showThread(){
System.out.println(Thread.currentThread().getName());
}
}
複製程式碼
5.6 修改ProductController
@RestController
public class ProductController {
@Autowired
private ProductService userService;
@RequestMapping("/consumer")
public List<Product> getUsers(){
return userService.getUsers();
}
@RequestMapping("/consumer1")
public void getUsers1(){
userService.showThread();
}
}
複製程式碼
5.7 執行緒池隔離引數
6.隔離(訊號量隔離)
6.1 建立專案
6.2 新增座標
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency>
複製程式碼
6.3 修改配置檔案
spring.application.name=eureka-consumer-ribbon-semaphore
server.port=9010
#設定服務註冊中心地址,向所有註冊中心做註冊
eureka.client.serviceUrl.defaultZone=http://user:123456@eureka1:8761/eureka/,http://user:123456@eureka2:8761/eureka/
複製程式碼
6.4 修改啟動類
//開啟熔斷器
@EnableCircuitBreaker
//表示Eureka的客戶端
@EnableEurekaClient
@SpringBootApplication
public class ConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(ConsumerApplication.class,args);
}
}
複製程式碼
6.5 修改ProductService
@Service
public class ProductService {
@Autowired
private LoadBalancerClient loadBalancerClient; //ribbon:負載均衡器
@HystrixCommand(groupKey = "ego-product-provider","我是託底資料"));
return list;
}
public void showThread(){
System.out.println(Thread.currentThread().getName());
}
}
複製程式碼
6.6 訊號量隔離引數
三、執行緒池隔離和訊號量隔離的區別
四、Feign的雪崩處理
1.Feign的服務降級處理
1.1 建立專案
1.2 修改配置檔案
spring.application.name=springcloud-eureka-consumer-feign-fallback
server.port=9020
#設定服務註冊中心地址,向所有註冊中心做註冊
eureka.client.serviceUrl.defaultZone=http://user:123456@eureka1:8761/eureka/,http://user:123456@eureka2:8761/eureka/
#feign預設是不開啟hystrix,預設值為false
feign.hystrix.enabled=true
複製程式碼
1.3 修改ProductConsumerService
//指定實現該介面的服務
@FeignClient(name = "ego-product-provider",fallback = ProductServiceFallback.class)
public interface ProductConsumerService {
//查詢所有商品
@RequestMapping(value = "/product/findAll",method = RequestMethod.GET)
public List<Product> findAll();
}
複製程式碼
1.4 新增ProductServiceFallback
@Component
public class ProductServiceFallback implements ProductConsumerService {
/**
* 能夠返回託底資料的fallback方法
* @return
*/
@Override
public List<Product> findAll() {
ArrayList<Product> list = new ArrayList<>();
list.add(new Product(-1,"我是託底資料"));
return list;
}
}
複製程式碼
1.5 修改ProductController
@RestController
public class ProductController {
@Autowired
private ProductConsumerService consumerService;
/**
* Consumer中查詢所有商品的方法
* @return
*/
@RequestMapping(value = "/list",method = RequestMethod.GET)
public List<Product> list(){
return consumerService.findAll();
}
}
複製程式碼
2.降級後的異常記錄
2.1 建立專案
2.2 新增ProductServiceFallbackFactory類
@Component
public class ProductServiceFallbackFactory implements FallbackFactory<ProductConsumerService> {
Logger logger = LoggerFactory.getLogger(ProductServiceFallbackFactory.class);
@Override
public ProductConsumerService create(final Throwable throwable) {
return new ProductConsumerService() {
/**
* 能夠返回託底資料的fallback方法
* @return
*/
@Override
public List<Product> findAll() {
logger.warn("Fallback Exception: ",throwable);
ArrayList<Product> list = new ArrayList<>();
list.add(new Product(-1,"我是託底資料"));
return list;
}
};
}
}
複製程式碼
2.3 修改ProductConsumerService
//指定實現該介面的服務
@FeignClient(name = "ego-product-provider",fallbackFactory = ProductServiceFallbackFactory.class)
public interface ProductConsumerService {
//查詢所有商品
@RequestMapping(value = "/product/findAll",method = RequestMethod.GET)
public List<Product> findAll();
}
複製程式碼
五、視覺化的資料監控 Hystrix-dashboard
Hystrix-dashboard是一款針對Hystrix進行實時監控的工具,通過Hystrix-dashboard我們可以直觀的看到各 Hystrix Command的請求響應時間,請求成功率等資料。
1.建立專案
2.新增座標
<?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>1.5.13.RELEASE</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<groupId>com.luyi</groupId>
<artifactId>springcloud-eureka-consumer-ribbon-dashboard</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>springcloud-eureka-consumer-ribbon-dashboard</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Dalston.SR5</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<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>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-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>
複製程式碼
3.修改啟動類
//開啟熔斷器
@EnableCircuitBreaker
//表示Eureka的客戶端
@EnableEurekaClient
@SpringBootApplication
@EnableHystrix
@EnableHystrixDashboard
public class ConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(ConsumerApplication.class,args);
}
}
複製程式碼
訪問: http://localhost:9010/hystrix.stream 檢視資訊
4.Hystrix-dashboard監控中心
4.1 建立專案
4.2 新增座標
<?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>1.5.13.RELEASE</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<groupId>com.luyi</groupId>
<artifactId>springcloud-eureka-consumer-dashboard-view</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>springcloud-eureka-consumer-dashboard-view</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Dalston.SR5</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<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>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-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>
複製程式碼
4.3 修改配置檔案
spring.application.name=eureka-consumer-hystrix-dashboard
server.port=1001
#設定服務註冊中心地址,向所有註冊中心做註冊
eureka.client.serviceUrl.defaultZone=http://user:123456@eureka1:8761/eureka/,http://user:123456@eureka2:8761/eureka/
複製程式碼
4.4 修改啟動類
//開啟熔斷器
@EnableCircuitBreaker
//表示Eureka的客戶端
@EnableEurekaClient
@SpringBootApplication
@EnableHystrix
@EnableHystrixDashboard
public class ConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(ConsumerApplication.class,args);
}
}
複製程式碼
4.5 啟動順序
先啟動dashboard,再啟動dashboard-view
4.6 訪問監控中心
訪問:localhost:1001/hystrix
4.7 監控中心圖解
六、使用Turbine在多個服務與叢集情況下收集資料監控
Turbine 是聚合伺服器傳送事件流資料的一個工具,hystrix 的 監控中,只能監控單個節點,實際生產中都為叢集,因此可以通過 turbine 來監控叢集服務。
1.建立Turbine專案
1.1 新增座標
<?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>1.5.13.RELEASE</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<groupId>com.luyi</groupId>
<artifactId>springcloud-eureka-consumer-turbine</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>springcloud-eureka-consumer-turbine</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Dalston.SR5</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<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>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix-dashboard</artifactId>
</dependency>
<!--新增turbine座標-->
<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.2 修改配置檔案
spring.application.name=eureka-consumer-hystrix-turbine
server.port=1002
#設定服務註冊中心地址,向所有註冊中心做註冊
eureka.client.serviceUrl.defaultZone=http://user:123456@eureka1:8761/eureka/,http://user:123456@eureka2:8761/eureka/
#---------------------------------------turbine--------------------------
#配置 Eureka 中的 serviceId 列表,表明監控哪些服務
turbine.appConfig=eureka-consumer-ribbon-threadpool,springcloud-eureka-consumer-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.3 修改啟動類
@SpringBootApplication
@EnableTurbine
public class HystrixTurbineApplication {
public static void main(String[] args) {
SpringApplication.run(HystrixTurbineApplication.class,args);
}
}
複製程式碼
2.使用Turbine聚合多個服務
2.1 修改被聚合的專案的pom檔案,新增dashboard的座標
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix-dashboard</artifactId>
</dependency>
複製程式碼
2.2 修改被監控的服務的啟動類
@EnableDiscoveryClient
@EnableFeignClients
@SpringBootApplication
//必須新增如下兩個註解
@EnableCircuitBreaker
@EnableHystrixDashboard
public class ConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(ConsumerApplication.class,args);
}
}
複製程式碼
2.3 檢視turbine整合成功後的監控地址
檢視:http://localhost:1002/turbine.stream
七、使用RabbitMQ收集、監控資料
使用RabbitMQ可以解決服務與turbine緊耦合問題,另外使用tuebine需要在配置檔案中指定需要收集的服務名,如果服務很多的話,配置起來也比較麻煩。
1.建立Consumer服務
2.新增座標
<?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>1.5.13.RELEASE</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<groupId>com.luyi</groupId>
<artifactId>springcloud-eureka-consumer-ribbon-dashboard-mq</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>springcloud-eureka-consumer-ribbon-dashboard-mq</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Dalston.SR5</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<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>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-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>
複製程式碼
3.修改consumer的配置檔案
spring.application.name=eureka-consumer-ribbon-dashboard
server.port=9010
#設定服務註冊中心地址,向所有註冊中心做註冊
eureka.client.serviceUrl.defaultZone=http://user:123456@eureka1:8761/eureka/,http://user:123456@eureka2:8761/eureka/
spring.rabbitmq.host=192.168.234.128
spring.rabbitmq.port=5672
spring.rabbitmq.username=luyi
spring.rabbitmq.password=luyi
spring.rabbitmq.virtual-host=/
複製程式碼
4.修改啟動類
//開啟熔斷器
@EnableCircuitBreaker
//表示Eureka的客戶端
@EnableEurekaClient
@SpringBootApplication
@EnableHystrix
@EnableHystrixDashboard
public class ConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(ConsumerApplication.class,args);
}
}
複製程式碼
5.建立Turbine專案
6.為Turbine專案新增依賴
<?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>1.5.13.RELEASE</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<groupId>com.luyi</groupId>
<artifactId>springcloud-eureka-consumer-turbine-mq</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>springcloud-eureka-consumer-turbine-mq</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Dalston.SR5</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<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>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-turbine-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>
複製程式碼
7.修改Turbine的配置檔案
spring.application.name=eureka-consumer-hystrix-turbine
server.port=1002
#設定服務註冊中心地址,向所有註冊中心做註冊
eureka.client.serviceUrl.defaultZone=http://user:123456@eureka1:8761/eureka/,http://user:123456@eureka2:8761/eureka/
#rabbitmq與turbine相連線
spring.rabbitmq.host=192.168.234.128
spring.rabbitmq.port=5672
spring.rabbitmq.username=luyi
spring.rabbitmq.password=luyi
spring.rabbitmq.virtual-host=/
複製程式碼
8.修改Turbine啟動類
@SpringBootApplication
@EnableTurbineStream
public class HystrixTurbineApplication {
public static void main(String[] args) {
SpringApplication.run(HystrixTurbineApplication.class,args);
}
}
複製程式碼