SpringCloud(六)Hystrix——斷路器

剛出差回來,忙完一陣子,今天得以有空,那就多多更新下博客了。

源碼託管地址:https://github.com/cddofficial/SpringCloudRepo

目錄

1 雪崩效應

2. 解決方案

2.1 超時機制

2.1.1 使用RestTemplate+Ribbon

2.1.2 使用Feign

2.2 斷路器hystrix

3 hystrix斷路器

3.1 簡介

3.2 Ribbon與Hystrix實戰

3.2.1 複製得到eureka-client-coke-ribbon-hystrix微服務

3.2.2 修改eureka-client-coke-ribbon-hystrix

3.2.3 測試

3.3 Feign與Hystrix實戰

3.3.1 複製得到微服務eureka-client-coke-feign-hystrix

3.3.2 修改eureka-client-coke-feign-hystrix

3.3.3 測試

3.3.4 Fallback的升級FallbackFactory

3.4 Hystrix監控

3.4.1 初步查看監控信息

3.4.2 Dashboard查看監控信息


1 雪崩效應

前面我們知道了微服務間是如何通信的,在一個複雜的業務場景中,可能處理一個業務邏輯,要調用很多個微服務,其中最後一個要調用的微服務發生了異常,後面的一連串微服務調用都會發生異常,導致這個異常範圍越來越大,最後甚至整服務器集羣都會癱瘓。這就是傳說中的可怕的 雪崩效應

接下來,給大家用圖演示下,雪崩效應。各個服務器狀態,綠色表示正常,紅色表示異常。

2019-11-25 15:44:25,服務器A發生異常,如下圖:

2019-11-25 15:44:45,服務器A,B,C發生異常,如下圖:

2019-11-25 15:45:05,服務器A,B,C,D,E整個服務器都發生異常,如下圖:

那麼我們如何避免這種級聯失敗(雪崩效應)呢?請繼續往下看。

2. 解決方案

2.1 超時機制

       通過網絡請求其他服務,都必須設置超時。正常情況下,一個遠程調用RPC(Remote Procedure Call)一般在幾十毫秒內就響應了。當依賴不可用或者因爲網絡問題,響應會變得特別長。而通常情況下,一個RPC對應了一個線程/進程,如果響應太慢,那麼這個線程/進程將得不到釋放。每一個線程/進程對會耗費一部分資源,當有大量線程/進程得不到釋放,服務器資源會被耗盡,會導致很多服務不可用。所以每個請求都必須設置超時時間。

2.1.1 使用RestTemplate+Ribbon

在向spring容器中註冊RestTemplate的bean時,設置其超時時間,如下圖:

附加

有人可能會說設置ribbon超時時間,目前我們這個版本的不允許這樣設置,就算設置了也不會生效,設置方式如下:

爲什麼沒生效呢?我們來看下源碼,RibbonProperties類。

並沒有setReadTimeout方法

也沒有setConnectTimeout方法

這應該就是在application.yml中設置ribbon超時時間不生效的原因吧,其他的SpringCloud版本我沒有試。大家有興趣可以去試一試,可以多多交流。

2.1.2 使用Feign

# feign也支持hystrix,設置超時時間
hystrix.command.serverMethod.execution.isolation.thread.timeoutInMilliseconds: 1000

2.2 斷路器hystrix

 我們先了解斷路器,在我們的日常生活中,每個人家裏都應該有斷路器,就是我們日常所說的管電的閘,當我們正在用一個大功率的電器時,電線電流過大,這時候要是不關閉電源可能電線會着火發生火災。我們靠什麼來及時快速的切斷電源呢(當電流電壓異常時),就是斷路器,我們日常的所說的電閘。

同樣的道理,在系統中有大量的請求超時了,再不會讓服務消費者去再次請求了,這裏就要用到斷路器避免不必要的資源浪費。

斷路器的原理是當判斷服務異常時(例如:有大量請求超時),會讓後面再來請求快速失敗。斷路器模式就像是那些容易導致錯誤的一種代理。這種代理能夠記錄最近調用發生錯誤的次數。然後決定是否允許操作繼續或者立即返回錯誤。

3 hystrix斷路器

3.1 簡介

hystrix 中文名爲“豪豬”,即平時很溫順,在感受到危險的時候,用刺保護自己;在危險過去後,還是一個溫順的肉球。

Hystrix是Netflix的一個防止級聯失敗的類庫。

3.2 Ribbon與Hystrix實戰

3.2.1 複製得到eureka-client-coke-ribbon-hystrix微服務

複製eureka-client-coke-ribbon微服務重命名爲eureka-client-coke-ribbon-hystrix(如何複製?請看eureka——實戰中的 “2.4.1 創建可樂微服務” 的 “複製得到eureka-client-coke),導入到IDE工具中。如下圖:

3.2.2 修改eureka-client-coke-ribbon-hystrix

1 添加依賴

給pom文件中添加hystrix依賴,如下圖:

整個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.0.7.RELEASE</version>
		<relativePath /> <!-- lookup parent from repository -->
	</parent>
 
	<groupId>com.cdd.cloud</groupId>
	<artifactId>eureka-client-coke-ribbon-hystrix</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>eureka-server-service-discover</name>
	<description>Demo project for Spring Boot</description>
 
	<properties>
		<java.version>1.8</java.version>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
	</properties>
 
	<dependencies>
		<!-- hystrix依賴 -->
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
		</dependency>
		
		<!-- eureka client依賴 -->
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
		</dependency>
 
		<!-- web依賴 -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
 
		<!-- 連接mysql所需依賴 -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-jdbc</artifactId>
		</dependency>
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<scope>runtime</scope>
		</dependency>
 
		<!-- 測試需要依賴 -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
	</dependencies>
 
	<!-- 引入spring cloud的依賴,不能少,主要用來管理Spring Cloud生態各組件的版本 -->
	<dependencyManagement>
		<dependencies>
			<dependency>
				<groupId>org.springframework.cloud</groupId>
				<artifactId>spring-cloud-dependencies</artifactId>
				<version>Finchley.SR2</version>
				<type>pom</type>
				<scope>import</scope>
			</dependency>
		</dependencies>
	</dependencyManagement>
 
	<!-- 添加spring-boot的maven插件,不能少,打jar包時得用 -->
	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>
 
</project>

2 修改啓動類

修改啓動類的名稱爲:EurekaClientCokeRibbonHystrixApplication,並且給啓動類上打上註解@EnableCircuitBreaker。啓動類代碼如下:

package com.cdd.demo;
 
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
 
@SpringBootApplication
@EnableEurekaClient  //eureka client 註解
@EnableCircuitBreaker  // 啓用斷路器
public class EurekaClientCokeRibbonHystrixApplication {
 
	public static void main(String[] args) {
		SpringApplication.run(EurekaClientCokeRibbonHystrixApplication.class, args);
	}
	
	@Bean   // 向spring容器中中註冊RestTemplate
	@LoadBalanced  // 負載均衡註解
	public RestTemplate restTemplate() {
		return new RestTemplate();
	}
}

3. 修改CokeController

給findById方法添加一個調用異常回調方法findByIdFallback,把該回調方法名通過@HystrixCommand註解配置到findById方法上。代碼如下:

package com.cdd.demo.controller;
 
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;

import com.cdd.demo.entity.User;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
 
@RestController
public class CokeController {
 
	// 注入RestTemplate
	@Autowired
	private RestTemplate restTemplate;
 
	// 通過RestTemplate向用戶微服務發送請求
	@GetMapping("/coke/{id}")
	@HystrixCommand(fallbackMethod="findByIdFallback")   // 發生異常回調方法,配置方法名
	public User findById(@PathVariable Long id) {	
		// 方法getForObject當前請求路徑參數已經換成了用戶微服務的 serviceId,
		return this.restTemplate.getForObject("http://eureka-client-user/user/" + id, User.class);
	}
	
	// 發生異常回調方法
	// 返回,參數要和原方法一致
	public User findByIdFallback(@PathVariable Long id) {
		User user = new User();
		user.setId(0l);
		user.setName("微服務");
		return user;
	}
}

 

3.2.3 測試

1. 啓動服務註冊服務

2. 啓動用戶微服務,啓動2個實例(詳情可以參照SpringCloud(五)Feign——更好用的通信方式中2.3啓動服務中2啓動用戶微服務)。切記要以debug模式啓動哦

3 啓動eureka-client-coke-ribbon-hystrix微服務

4 先來看下服務註冊列表,瀏覽器中輸入:http://localhost:8761/ ,響應頁面如下,可以服務都啓動成功了,並且也都註冊上了:

5 根據頁面響應測試

先給用戶微服務的UserController裏的findById方法打上一個斷點,如下圖:

接下來請求http://localhost:9001/coke/2

首先我們的IDE工具進入到了斷點,如下圖:

我們不釋放這個斷點,讓進程一直等在這個,這時候再回到瀏覽器頁面,可以看到響應頁面已經有了,返回了我們剛纔寫的回調方法findByIdFallback()方法執行的結果,如下圖:

到這裏說明我們剛纔的斷路器生效了。

6. 根據微服務健康信息測試

(1)pom文件添加依賴

給eureka-client-coke-ribbon-hystrix微服務的pom文件添加監控依賴,依賴截圖如下:

整個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.0.7.RELEASE</version>
		<relativePath /> <!-- lookup parent from repository -->
	</parent>

	<groupId>com.cdd.cloud</groupId>
	<artifactId>eureka-client-coke-ribbon-hystrix</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>eureka-server-service-discover</name>
	<description>Demo project for Spring Boot</description>

	<properties>
		<java.version>1.8</java.version>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
	</properties>

	<dependencies>
		<!-- hystrix依賴 -->
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
		</dependency>

		<!-- eureka client依賴 -->
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
		</dependency>

		<!-- web依賴 -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>

		<!-- 連接mysql所需依賴 -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-jdbc</artifactId>
		</dependency>
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<scope>runtime</scope>
		</dependency>

		<!-- 監控依賴 -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-actuator</artifactId>
		</dependency>

		<!-- 測試需要依賴 -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
	</dependencies>

	<!-- 引入spring cloud的依賴,不能少,主要用來管理Spring Cloud生態各組件的版本 -->
	<dependencyManagement>
		<dependencies>
			<dependency>
				<groupId>org.springframework.cloud</groupId>
				<artifactId>spring-cloud-dependencies</artifactId>
				<version>Finchley.SR2</version>
				<type>pom</type>
				<scope>import</scope>
			</dependency>
		</dependencies>
	</dependencyManagement>

	<!-- 添加spring-boot的maven插件,不能少,打jar包時得用 -->
	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>

</project>

(2)配置顯示詳細健康信息

在eureka-client-coke-ribbon-hystrix微服務的application.yml文件中,配置顯示詳細健康信息。Spring Boot 1.x與2.x端點的差異比較大,詳情可參照:https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-2.0-Migration-Guide#endpoints

application.yml中新增配置截圖如下:

整個文件代碼如下:

server:
  port: 9001
 
spring:
  application:
    name: eureka-client-coke  #服務名稱
  datasource:
    url: jdbc:mysql://localhost:3306/test?serverTimezone=UTC&useUnicode=true&characterEncoding=utf8
    driver-class-name: com.mysql.jdbc.Driver
    username: root
    password: root
    
eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:8761/eureka/
  instance:
    prefer-ip-address: true  #顯示真實ip,不是必須的
    

#顯示服務器詳細的健康信息
management:
  endpoint:
    health:
      show-details: always  # 是否展示健康檢查詳情

(3)重新啓動eureka-client-coke-ribbon-hystrix微服務(服務註冊服務,兩個用戶微服務實例也要在運行狀態哦)

(4)瀏覽器請求:http://localhost:9001/actuator/health,響應頁面如下,可以看到這個服務的很多信息,主要看下面的斷路器hystrix狀態信息(這裏用的時火狐瀏覽器,響應的json數據會一個樹狀展示更好看;用google瀏覽器返回的就是一堆數據了)。

(5)接下來我們把用戶微服務的兩個實例全部停掉,多次刷新請求http://192.168.50.12:9001/coke/1頁面(實際上去向用戶微服務發請求了,這時候用戶微服務停掉了,肯定會觸發斷路器打開)。刷新多次等會再去訪問http://localhost:9001/actuator/health,就可以看到斷路器打開了。(至於http://192.168.50.12:9001/coke/1請求要刷新幾次等多久我具體也沒記時過,可以兩個請求輪流刷,一會就可以看到斷路器打開了,不會要很長時間的),如下圖:

3.3 Feign與Hystrix實戰

3.3.1 複製得到微服務eureka-client-coke-feign-hystrix

複製eureka-client-coke-feign微服務重命名爲eureka-client-coke-feign-hystrix(如何複製?請看eureka——實戰中的 “2.4.1 創建可樂微服務” 的 “複製得到eureka-client-coke),導入到IDE工具中。如下圖:

3.3.2 修改eureka-client-coke-feign-hystrix

1.添加依賴

(1)hystrix依賴

feign很好的支持了hystrix所以,不用再引入hystrix依賴了。我們可以pom文件中所示hystrix,就可以搜到hystrix相關依賴(注意:feign對hystrix的支持只是部分支持,再用到某些功能hystrix的某些功能時,還要引入hystrix依賴。例如:hystrix.stream),如下圖:

(2)監控依賴

在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.0.7.RELEASE</version>
		<relativePath /> <!-- lookup parent from repository -->
	</parent>

	<groupId>com.cdd.cloud</groupId>
	<artifactId>eureka-client-coke-feign-hystrix</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>eureka-server-service-discover</name>
	<description>Demo project for Spring Boot</description>

	<properties>
		<java.version>1.8</java.version>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
	</properties>

	<dependencies>
		<!-- feign組件依賴 -->
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-openfeign</artifactId>
		</dependency>

		<!-- eureka client依賴 -->
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
		</dependency>

		<!-- web依賴 -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>

		<!-- 連接mysql所需依賴 -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-jdbc</artifactId>
		</dependency>
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<scope>runtime</scope>
		</dependency>

		<!-- 監控依賴 -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-actuator</artifactId>
		</dependency>

		<!-- 測試需要依賴 -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
	</dependencies>

	<!-- 引入spring cloud的依賴,不能少,主要用來管理Spring Cloud生態各組件的版本 -->
	<dependencyManagement>
		<dependencies>
			<dependency>
				<groupId>org.springframework.cloud</groupId>
				<artifactId>spring-cloud-dependencies</artifactId>
				<version>Finchley.SR2</version>
				<type>pom</type>
				<scope>import</scope>
			</dependency>
		</dependencies>
	</dependencyManagement>

	<!-- 添加spring-boot的maven插件,不能少,打jar包時得用 -->
	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>

</project>

2.修改application.yml文件

在feign中hystrix是默認不開啓的,首先開啓斷路器hystrix,截圖如下:

展示健康檢查詳情,修改的部分截圖如下:

最後整個application.yml文件內容如下:

server:
  port: 9001
 
spring:
  application:
    name: eureka-client-coke  #服務名稱
  datasource:
    url: jdbc:mysql://localhost:3306/test?serverTimezone=UTC&useUnicode=true&characterEncoding=utf8
    driver-class-name: com.mysql.jdbc.Driver
    username: root
    password: root
    
eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:8761/eureka/
  instance:
    prefer-ip-address: true  #顯示真實ip,不是必須的
    
feign:
  hystrix:
    enabled: true  #開啓斷路器
    
management:
  endpoint:
    health:
      show-details: always  #展示健康檢查詳情

3. 修改啓動類

啓動類重命名爲EurekaClientCokeFeignHystrixApplication,啓動類上也不用打@EnableCircuitBreaker 註解了,修改後的代碼如下:

package com.cdd.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.openfeign.EnableFeignClients;

@SpringBootApplication
@EnableEurekaClient  //eureka client 註解
@EnableFeignClients  //啓用feign組件註解
public class EurekaClientCokeFeignHystrixApplication {

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

4.新建HystrixClientFallback類

com.cdd.demo包下新建一個包config,在config包下新建一個HystrixClientFallback類,該類代碼如下:

package com.cdd.demo.config;

import org.springframework.stereotype.Component;

import com.cdd.demo.entity.User;
import com.cdd.demo.feign.UserFeignClient;

@Component
public class HystrixClientFallback implements UserFeignClient{

	@Override
	public User findById(long id) {
		User user = new User();
		user.setId(-1L);
		user.setName("Fallback");
		return user;
	}

}

5.修改UserFeignClient接口

配置@FeignClient註解的fallback屬性值,代碼如下:

package com.cdd.demo.feign;

import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;

import com.cdd.demo.config.HystrixClientFallback;
import com.cdd.demo.entity.User;

@FeignClient(name="eureka-client-user",fallback=HystrixClientFallback.class)
public interface UserFeignClient {
	
	@GetMapping("/user/{id}")
	public User findById(@PathVariable long id);
}

3.3.3 測試

啓動服務註冊服務eureka-server-service-discover,啓動用戶微服務2個實例,啓動eureka-client-coke-feign-hystrix微服務。

測試方法和步驟和上面“3.2.3 測試”一樣,只不過回調頁面不同(這是我們剛纔配置在UserFeignClient接口@FeignClient註解裏面的HystrixClientFallback類的內容)如下:

其他基本都一樣。

3.3.4 Fallback的升級FallbackFactory

緊挨着的上面實例中我們給UserFeignClient接口的@FeignClient註解配置的是fallback屬性值,配置了這個屬性等服務提供者發生異常(實例中式用戶微服務發生異常了),不能打印異常信息。下面我們用FallbackFacotry來配置,等發生異常時,可以打印出異常信息。

1 複製得到eureka-client-coke-feign-hystrix-fallbackfactory微服務

複製eureka-client-coke-feign-hystrix微服務重命名爲eureka-client-coke-feign-hystrix-fallbackfactory(如何複製?請看eureka——實戰中的 “2.4.1 創建可樂微服務” 的 “複製得到eureka-client-coke),並且導入到IDE工具中,如下圖:

2 修改啓動類

修改啓動類的名稱爲EurekaClientCokeFeignHystrixFallbackFactoryApplication,啓動類代碼如下:

package com.cdd.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.openfeign.EnableFeignClients;

@SpringBootApplication
@EnableEurekaClient  //eureka client 註解
@EnableFeignClients  //啓用feign組件註解
public class EurekaClientCokeFeignHystrixFallbackFactoryApplication {

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

3.添加UserFeignClientWithFallbackFactory接口

在config包中添加UserFeignClientWithFallbackFactory接口,代碼如下:

package com.cdd.demo.config;

import com.cdd.demo.feign.UserFeignClient;

public interface UserFeignClientWithFallbackFactory extends UserFeignClient {
	
}

4. 添加HystrixClientFallbackFactory類

在config包中添加HystrixClientFallbackFactory類,代碼如下:

package com.cdd.demo.config;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import com.cdd.demo.entity.User;
import com.cdd.demo.feign.UserFeignClient;

import feign.hystrix.FallbackFactory;

@Component
public class HystrixClientFallbackFactory implements FallbackFactory<UserFeignClient> {

	private static final Logger LOG = LoggerFactory.getLogger(UserFeignClientWithFallbackFactory.class);

	@Override
	public UserFeignClient create(Throwable cause) {
		
		// 打印異常日誌
		LOG.info("fallback reason is:{}", cause.getMessage());
		
		// 制定回調方法
		return new UserFeignClientWithFallbackFactory() {
			@Override
			public User findById(long id) {
				User user = new User();
				user.setId(-2L);
				user.setName("Fallback的升級FallbackFactory");
				return user;
			}
			
		};
	}
}

5 修改UserFeignClient接口

修改該接口的@FeignClient註解裏面的屬性配置,現在來配置fallbackFactory屬性。代碼如下:

package com.cdd.demo.feign;

import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;

import com.cdd.demo.config.HystrixClientFallbackFactory;
import com.cdd.demo.entity.User;

@FeignClient(
		name="eureka-client-user",
//		fallback=HystrixClientFallback.class,  // fallback與fallbackFactory不能同時配置
		fallbackFactory=HystrixClientFallbackFactory.class)
public interface UserFeignClient {
	
	@GetMapping("/user/{id}")
	public User findById(@PathVariable long id);
}

6 測試

啓動服務註冊服務eureka-server-service-discover,啓動用戶微服務2個實例,啓動

eureka-client-coke-feign-hystrix-fallbackfactory微服務。

該微服務的健康信息和斷路器打開關閉,我們在這裏不測了,大家可以自己去試下。在這裏我們只測下響應頁面和是否打印出了異常日誌。

接着我們停掉用戶微服務的兩個實例,再來進行下面的測試。

瀏覽器請求:http://192.168.50.12:9001/coke/1  ,現在響應頁面就是我們剛纔在HystrixClientFallbackFactory類中的配置了,如圖:

再來看下eureka-client-coke-feign-hystrix-fallbackfactory微服務微服務的控制檯信息。

紅色框內日誌表示:負載均衡沒有可用的用戶微服務eureka-client-user。的確是這樣啊,我們剛纔手動停了用戶微服務的兩個實例。

 

3.4 Hystrix監控

微服務整合了Hystrix,同時當引入了spring-boot-starter-actuator 依賴,就會存在一個/actuator/hystrix.stream 端點,用來監控Hystrix Command。我們可以查看下該微服務的一些hystrix監控信息,請往下看。

3.4.1 初步查看監控信息

1. 修改eureka-client-coke-ribbon-hystrix微服務

我們在微服務eureka-client-coke-ribbon-hystrix的application.yml文件中去讓 /hystrix.stream端點暴露出來,默認是不暴露的。截圖如下:

整個application.yml文件代碼如下:

server:
  port: 9001
 
spring:
  application:
    name: eureka-client-coke  #服務名稱
  datasource:
    url: jdbc:mysql://localhost:3306/test?serverTimezone=UTC&useUnicode=true&characterEncoding=utf8
    driver-class-name: com.mysql.jdbc.Driver
    username: root
    password: root
    
eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:8761/eureka/
  instance:
    prefer-ip-address: true  #顯示真實ip,不是必須的
    

#顯示服務器詳細的健康信息
management:
  endpoint:
    health:
      show-details: always  # 是否展示健康檢查詳情
  endpoints:
    web:
      exposure:
        include: 'hystrix.stream'  # 暴露‘hystrix.stream’端點

2. 啓動服務

啓動服務註冊服務eureka-server-service-discover,用戶微服務eureka-client-user啓動兩個實例(以不同的端口號啓動兩次就行),啓動eureka-client-coke-ribbon-hystrix微服務。

啓動完成後,來查看下服務註冊列表。瀏覽器中訪問:localhost:8761,響應頁面如下:

3. 查看監控信息

先訪問下http://localhost:9001/coke/2請求(可樂微服務去請求用戶微服務)。響應頁面如下:

接下來在google瀏覽器(google瀏覽器會返回一堆數據,火狐瀏覽器會彈出一個下載文件框)中訪問http://localhost:9001/actuator/hystrix.stream,查看監控信息。如下圖:

3.4.2 Dashboard查看監控信息

Hystrix Dashboard是作爲斷路器狀態的一個組件,提供了數據監控和友好的圖形化界面。,說白了。就是通過配置Hystrix Dashboard去查看監控信息。

1. 複製得到hystrix-dashboard-demo項目

複製微服務eureka-server-service-discover重命名爲hystrix-dashboard-demo項目(如何複製?請看eureka——實戰中的 “2.4.1 創建可樂微服務” 的 “複製得到eureka-client-coke)。導入到IDE工具中,項目結構如下圖:

2 修改hystrix-dashboard-demo項目

(1)修改pom文件。

pom文件除過測試的依賴留下,其他依賴全部刪掉,再添加Dashboard依賴,截圖如下:

整個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.0.7.RELEASE</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	
	<groupId>com.cdd.cloud</groupId>
	<artifactId>hystrix-dashboard-demo</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>eureka-server-service-discover</name>
	<description>Demo project for Spring Boot</description>
 
	<properties>
		<java.version>1.8</java.version>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
	</properties>
 
	<dependencies>	
		<!-- dashboard依賴 -->
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
		</dependency>
		
		<!-- 測試依賴 -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
	</dependencies>
	
	<!-- 引入spring cloud的依賴,不能少,主要用來管理Spring Cloud生態各組件的版本 -->
    <dependencyManagement>
	    <dependencies>
	      <dependency>
	        <groupId>org.springframework.cloud</groupId>
	        <artifactId>spring-cloud-dependencies</artifactId>
	        <version>Finchley.SR2</version>
	        <type>pom</type>
	        <scope>import</scope>
	      </dependency>
	    </dependencies>
  	</dependencyManagement>
 
	<!-- 添加spring-boot的maven插件,不能少,打jar包時得用 -->
	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>
 
</project>

(2)修改application.yml文件

這個項目不註冊到服務註冊中心,只配置端口爲8090,整個application.yml文件內容如下:

server:
  port: 8090

3.啓動服務

啓動hystrix-dashboard-demo項目(服務註冊服務,用戶微服務的2個實例,eureka-client-coke-ribbon-hystrix微服務都要在運行狀態,沒有啓動的就先啓動吧)

4.Dashboard查看監控信息

(1)瀏覽器中先發個請求:http://localhost:9001/coke/2,如下圖:

(2)瀏覽器中再看下那一堆監控信息數據是否響應,訪問http://localhost:9001/actuator/hystrix.stream,如下圖:

(3)瀏覽器訪問http://localhost:8090/hystrix,進入監控首業,如下圖:

 

(4)在這個頁面中填入信息,如下圖

第一個紅色方框中的地址,就是第(2)步中的訪問地址。這裏配置延遲(delay):2秒,標題:“Hystrix-Dashboard-Demo”,點擊Monitor Stream按鈕。

之後彈出響應頁面如下圖,就是對微服務eureka-client-coke-ribbon-hystrix的監控信息了。

這個就是對監控信息的圖形化展示了。

這個實例是對微服務eureka-client-coke-ribbon-hystrix的監控,是對ribbon + hystrix應用的監控。那如果要對feign + hystrix應用的監控呢?其實是一樣的,唯一不同就是給feign + hystrix應用(例如:微服務eureka-client-coke-feign-hystrix)加上hystrix依賴。feign對hystrix的支持是部分的,要用hystrix.stream還需要引入hystrix依賴。

這個是對單個微服務進行監控,那麼多個的情況呢?這個如何解決,感興趣的同學可以看下turbine這個東西。當然也可以給我留言討論交流哦。

斷路器hystrix部分就說到這裏了,有什麼問題或建議歡迎大家提出來。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章