剛出差回來,忙完一陣子,今天得以有空,那就多多更新下博客了。
源碼託管地址:https://github.com/cddofficial/SpringCloudRepo
目錄
3.2.1 複製得到eureka-client-coke-ribbon-hystrix微服務
3.2.2 修改eureka-client-coke-ribbon-hystrix
3.3.1 複製得到微服務eureka-client-coke-feign-hystrix
3.3.2 修改eureka-client-coke-feign-hystrix
3.3.4 Fallback的升級FallbackFactory
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部分就說到這裏了,有什麼問題或建議歡迎大家提出來。