前言
在分佈式架構中,所謂的斷路器模式是指當某個服務發生故障之後,通過斷路器的故障監控,向調用方返回一個錯誤響應,這樣就不會使得線程因調用故障服務被長時間佔用不釋放,避免故障的繼續蔓延。Spring Cloud Hystrix實現了斷路器,線程隔離等一系列服務保護功能,它是基於Netflix的開源框架Hystrix實現的。
目的不是介紹Hystrix的與原理、及其使用等(有時間也要記錄啊),而是通過實戰搭建一個簡單的監控集羣,使用Hystrix Dashboard儀表盤動態監控展示以此來加深對Hystrix的認識與理解,爲什麼要記錄呢?這是因爲網上資料甚少(或版本過低,不適用),同時加之書中的Spring Cloud版本與現在Spring Boot 2.x差距明顯
本文主要參考《Spring Cloud 微服務實戰》(PDF電子版,需要的朋友可以私聊或評論)
一、Hystrix 儀表盤
1、認識Hystrix儀表盤
HystrixCommand與HystrixObserableCommand實例執行過程中記錄的重要信息稱之爲Hystrix儀表盤,以供內部或者外部進行查詢使用。Spring Cloud整合儀表盤組件Hystrix Dashboard,主要用來實時監控Hystrix的各項指標信息,可以幫我們快速發現系統中存在的問題,從而及時地採取應對措施。
1)加入依賴
特別注意Spring Boot 2.x版本引入的hystrix-dashboard依賴,不然可能訪問不了http://localhost:port/hystrix儀表盤頁面,註解@EnableHsytrixDashboard也可能找不到
<!-- hystrix 容錯機制 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-hystrix</artifactId> <version>${spring-cloud-eureka.version}</version> </dependency> <!-- actuator監控 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <!-- Spring Boot 2.x以上版本 spring-cloud-starter-netflix-hystrix-dashboard 儀表盤, 以下版本則需要spring-cloud-starter-hystrix-dashboard--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId> <version>${spring-cloud-eureka.version}</version> </dependency>
2)添加配置
# 應用實例
spring:
application:
name: hystrix-dashboard
server:
port: 8000
# actuator開放所有端點,Spring Boot 2.x與1.x不同,具體請查詢
management:
endpoints:
web:
exposure:
include: "*"
3)增加註解:應用主類加上@EnableHsytrixDashboard,啓用Hystrix Dashboard功能。
@EnableHystrixDashboard // 開啓Hystrix儀表盤 @SpringBootApplication public class HystrixMonitorApplication { public static void main(String[] args) { SpringApplication.run(HystrixMonitorApplication.class, args); } }
4)訪問http://localhost:8000/hystrix界面如下:
2、監控頁面介紹
從界面中我們就可以看到Hystrix Dashboard支持不同的三種監控方式:
1) 默認的集羣監控:通過URL http://turbine-hostname:port/turbine.stream
2) 指定的集羣監控:通過URL http://turbine-hostname:port/turbine.stream?cluster=[clusterName]開啓
3) 單體應用的監控:URL http://hystrix-app:port/hystrix.stream開啓,實現對具體某個服務實例的監控
前兩者關於集羣的監控需要整合turbine才能實現,而對於單體實例節點需要訪問實例的/hystrix.stream接口實現,我們自然需要爲服務實例添加端點。只需要添加acutator與hystrix依賴,應用主程序類開啓斷路器@EnableCircuitBreaker註解與@EnableHystrixDashboard註解即可。
其中的參數:
1)Delay:用來控制服務器上輪詢監控信息的延遲時間,默認爲2000ms。可以通過該配置該屬性降低客戶端的網絡和CPU消耗。
2)Ttile:對應進入監控後的的標題,如Hystrix,則進入監控頁面後如下圖紅框標題
此外,我們在URL框輸入我們需要監聽的某個服務實例/hystrix.stream接口,如http://localhost:8081/hystrix.stream,就可以進入監控頁面
監控頁面參數介紹:
1) 實心圓與曲線的含義
實心圓顏色:健康度從綠色、黃色、橙色、紅色遞減
實心圓大小:會根絕實例的請求流量發生變化,流量越大實心圓就越大。
曲線:用來記錄2分鐘內流量的相對變化,可以通過它來觀察流量的上升與下降。
2) 其它的指標參數:鼠標停留會顯示相應的說明
二、簡單監控架構
1、監控單實例的架構
1)架構圖
2)過程說明
-
- 服務提供者:HELLO-SERVICE,提供一個接口如:http:/HELLO-SERVER/hello,讓消費者通過restTemplate(封裝好的HTTP)調用消費
- 服務消費者:RIBBON-CONSUMER,會有ribbon承擔負載均衡的作用,分別輪詢訪問HELLO-SERVER-1與HELLO-SERVICE-2
- 註冊中心:Spring Cloud Eureka,主要負責服務治理:服務的註冊、續約、剔除(更新)等
- Hystrix儀盤表:通過/hystrix.stream接口監控某個服務實例,動態展示儀表盤數據。
然而現在只針對一個實例來監控,而分佈式系統中往往有很多實例,我們就需要利用Turbine和Hystrix Dashboard配置實現對集羣的監控
2、監控聚合服務
需要通過Turbine來聚合RIBBON-CONSUMER-1與服務RIBBON-CONSUMER-2成一個服務展示監控信息,並輸出到Hystrix Dashboard中,只顯示一張監控圖,但是注意Hosts的數量爲2
(1)架構圖
(2)過程說明
同上述“單實例監控”,不同的是這次服務消費者有RIBBON-CONSUMER-1與RIBBON-CONSUMER-2兩個,通過/turbine.stream接口聚合兩個服務實例(實則就是同一個服務不同實例)成一個服務,共同動態展示整個集羣的動態數據。對於集羣來說關注的是服務集羣的高可用性,所以Turbine會將相同服務作爲整體看待。
三、代碼實踐
1、實踐前的準備
首先本示例使用的是Idea+Maven構造的項目工程的,所以先熟悉下idea如何構建一個簡單的Spring Boot項目
1)新建項目:File->New->Project
2)選擇Spring Initializr,選擇默認的https://start.spring.io(需要聯網),點擊Next
3)填寫項目信息
4)選擇依賴,這裏我們只需要選擇web依賴即可,之後再加入相關Spring Cloud Hystrix的依賴,這是因爲Spring Boot版本與Spring Cloud版本有相對應的關係,不然會衝突項目到處都是坑
5)查看Spring Boot與Spring Cloud的版本對應關係從官網(https://spring.io/projects/spring-cloud)中查看,這裏使用的是Spring Boot 2.0.6.RELEASE與Spring Cloud Fincley.SR1
6)我們需要搭建以下的架構
從圖中我們知道我們需要:
1)兩個Eureaka Server提供高可用的註冊中心:
分別對應工程eureka-server與eureke-slave-server,配置文件中register-with-eureka與fetch-registry保持默認true,相互註冊進行同步維護服務實例列表。
2)兩個服務提供者實例提供HELLO-SERVICE/hello服務:
對應工程hello-service,打包成jar包後通過命令 java -jar hello-service-0.0.1-SNAPSHOT.jar --server.port=8081 開啓實例HELLO-SERVICE-1,通過命令 java -jar hello-service-0.0.1-SNAPSHOT.jar --server.port=8082 開啓實例HELLO-SERVICE-2
3)兩個服務消費者實例消費HELLO-SERVICE/hello服務
對應工程ribbon-consumer,打包jar包後通過命令 java -jar ribbon-consumer-0.0.1-SNAPSHOT.jar --server.port=8083 開啓實例RIBBON-CONSUMER-1,通過命令 java -jar ribbon-consumer-0.0.1-SNAPSHOT.jar --server.port=8084 開啓實例RIBBON-CONSUMER-2
4)開啓Spring Cloud Circuit Breaker 斷路器
引入相關依賴,應用程序中開啓註解即可,具體請看下面示例。
5)消費者開啓負載均衡器
服務消費者直接通過調用被@LoadBalanced註解修飾過的RestTemplate來實現面向服務的接口調用
6)開啓Hystrix Dashboard儀表盤
引入hystrix dashboard、turbine等相關依賴,應用程序中開啓註解即可,具體請看下面示例。
2、代碼示例
1)服務治理工程:eureka-service與eureka-slave-service
pom.xml文件內容:eureka-service與eureka-slave-service都相同
<properties> <java.version>1.8</java.version> <spring-cloud.version>Finchley.SR1</spring-cloud.version> <spring-cloud-eureka.version>1.4.6.RELEASE</spring-cloud-eureka.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- Spring Cloud Eureka--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka-server</artifactId> <version>${spring-cloud-eureka.version}</version> </dependency> <!-- 可以刪除(需要同時刪除Test類),但是爲了不麻煩就保留了 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>${spring-cloud.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>
eureka-service的application.yml文件:
server:
port: 5678
eureka:
instance:
hostname: master
# slave註冊中心url
client:
service-url:
defaultZone: http://slave:5679/eureka/
# 關閉保護模式
server:
enable-self-preservation: false
eureka-slave-service的application.yml文件:
server:
port: 5679
eureka:
instance:
hostname: slave
client:
service-url:
defaultZone: http://master:5678/eureka/
server:
enable-self-preservation: false
注:需要在hosts文件中添加slave/master域名解析。
應用程序類開啓@EnableEurekaServer註解,表明是註冊中心服務器
@EnableEurekaServer @SpringBootApplication public class EurekaSlaveServerApplication { public static void main(String[] args) { SpringApplication.run(EurekaSlaveServerApplication.class, args); } }
2)服務提供者工程:hello-service
pom.xml文件內容:
注:這裏加入的依賴是spring-cloud-starter-eureka,不是spring-cloud-starter-eureka-server
<properties> <java.version>1.8</java.version> <spring-cloud.version>Finchley.SR1</spring-cloud.version> <spring-cloud-eureka.version>1.4.6.RELEASE</spring-cloud-eureka.version> </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-eureka</artifactId> <version>${spring-cloud-eureka.version}</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>${spring-cloud.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>
application.yml配置文件:
spring:
application:
name: hello-service
# 註冊中心url
eureka:
client:
service-url:
defaultZone: http://master:5678/eureka/,http://slave:5679/eureka/
instance:
# 定義服務失效的時間,默認爲90s。
lease-expiration-duration-in-seconds: 60
# 續約任務的調用時間間隔,默認爲30s
lease-renewal-interval-in-seconds: 10
應用程序增加註解@EnableEurekaClient
@EnableEurekaClient @SpringBootApplication public class EurekaClientApplication { public static void main(String[] args) { SpringApplication.run(EurekaClientApplication.class, args); } }
編寫/hello接口,提供消費者調用
@EnableEurekaClient
@SpringBootApplication
public class EurekaClientApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaClientApplication.class, args);
}
}