一、簡述
hystri:熔斷器
如果一個請求需要調起多個服務時,其中一個服務不通或失敗,當大量請求發生時,會導致請求延時和資源浪費。Hystrix是一個用於處理分佈式系統的延遲和容錯的開源庫,在分佈式系統裏,許多依賴不可避免的會調用失敗,比如超時、異常等,Hystrix能夠保證在一個依賴出問題的情況下,不會導致整體服務失敗,避免級聯故障,以提高分佈式系統的彈性。
當某個服務單元發生故障之後,通過斷路器的故障監控,向調用方返回一個符合預期的、可處理的備選響應(FallBack),而不是長時間的等待或者拋出調用方無法處理的異常,這樣就保證了服務調用方的線程不會被長時間、不必要地佔用,從而避免了故障在分佈式系統中的蔓延,乃至雪崩。
Hystrix可用於服務熔斷、服務降級、服務限流等作用。
個人理解,服務雪崩:
默認情況下tomcat只有一個線程池處理請求,假設共有50個線程,然後出現100個併發請求,如果某個接口處理時間過長,導致50個線程都被佔用,那麼另外的50個客戶請求將不能被響應。
二、服務熔斷
當某個服務出現異常時,熔斷該服務,快速返回指定的錯誤信息,當服務正常時,恢復熔斷。
1.創建module
複製module:microservice-provider1001命名爲microservice-provider-hystrix1004
2.添加依賴
<!-- hystrix -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency>
3.修改配置
修改端口、數據庫、eureka實例名稱等信息application.yml:
server:
port: 1004
mybatis:
config-location: "classpath:mybatis/mybatis.cfg.xml" # mybatis配置文件所在路徑
mapper-locations:
- "classpath:mybatis/mapper/**/*.xml" # mapper映射文件
type-aliases-package: com.syr.springcloud.entity # 別名類所在包
spring:
application:
name: microservicecloud-provider #微服務的名字
datasource:
driver-class-name: org.gjt.mm.mysql.Driver # mysql驅動包
type: com.alibaba.druid.pool.DruidDataSource # 當前數據源操作類型
url: "jdbc:mysql://localhost:3306/user04" # 數據庫名稱
username: root
password: mysql
dbcp2:
initial-size: 5 # 初始化連接數
max-total: 5 # 最大連接數
max-wait-millis: 200 # 等待連接獲取的最大超時時間
min-idle: 5
eureka:
client:
service-url:
defaultZone: http://eureka2001.com:2001/eureka/,http://eureka2002.com:2002/eureka/,http://eureka2003.com:2003/eureka/
instance:
instance-id: microservicecloud-provider-hystrix1004 #服務主機名稱
prefer-ip-address: true #訪問路徑可以顯示IP地址
info:
app.name: microservicecloud-provider
company.name: www.syr.com
build.artifactId: $project.artifactId$
build.version: $project.version$
#logging:
# level:
# com.syr.provider.mapper: debug
4.修改controller
這裏我只寫了兩個查詢的例子:
@GetMapping(value = "{id}")
@HystrixCommand(fallbackMethod = "fallback_get")//一旦調用失敗,執行fallback_get方法
public User get(@PathVariable("id")int id) {
User user=service.getUser(id);
if(user==null) {
throw new RuntimeException("沒有該用戶");
}
return user;
}
public User fallback_get(@PathVariable("id")int id) {
return User.builder().id(id).name("沒有該用戶").build();
}
@GetMapping
@HystrixCommand(fallbackMethod = "fallback_get")
public List<User> get() {
List<User> users=service.getUsers();
if(users==null||users.isEmpty()) {
throw new RuntimeException("沒有用戶");
}
return users;
}
public List<User> fallback_get() {
List<User> users=new ArrayList<User>();
return users;
}
5.啓動hystrix
@SpringBootApplication
@EnableEurekaClient
@EnableCircuitBreaker
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
6.測試
三、服務降級
在一個分佈式系統中,當訪問高峯期或資源有限時,需要關掉某個服務,若有請求訪問該服務,不能因爲系統服務關掉了,就一直中斷在該調用服務處,這時就需要請求返回指定的錯誤信息。例如在分佈式系統中有A、B兩個服務,因爲資源有限,需要關掉B服務,A服務在調用B服務時,沒有調通,此時A返回指定的錯誤信息,注意不是在B服務端返回的,是A客戶端返回的錯誤信息。
對比熔斷是在服務端本身進行錯誤處理,而服務降級則是在消費端進行處理。如果出現資源不足的情況,我就可以手動把不重要的服務關掉,這樣在消費端的降級處理會友好的告訴用戶,而不是400等頁面。
1.創建module
複製microservice-consumer-feign8080爲microservice-consumer-feign-hystrix8080
2.添加依賴
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency>
3.實現FallbackFactory接口
新建UserServiceFallbackFactory類實現FallbackFactory接口如下:
package com.syr.consumer.service.fallback;
import java.util.ArrayList;
import java.util.List;
import org.springframework.stereotype.Component;
import com.syr.api.entity.User;
import com.syr.consumer.service.UserService;
import feign.hystrix.FallbackFactory;
@Component
public class UserServiceFallbackFactory implements FallbackFactory<UserService>{
@Override
public UserService create(Throwable cause) {
return new UserService() {
@Override
public boolean put(User user) {
// TODO Auto-generated method stub
return false;
}
@Override
public boolean post(User user) {
// TODO Auto-generated method stub
return false;
}
@Override
public List<User> get() {
// TODO Auto-generated method stub
return new ArrayList<User>();
}
@Override
public User get(int id) {
// TODO Auto-generated method stub
return new User(id, "沒有數據", 0, null);
}
@Override
public boolean delete(int id) {
// TODO Auto-generated method stub
return false;
}
};
}
}
目的是讓Userservice執行失敗的時候由hystrix找到該類重寫的方法,
這裏我只測試了兩個查詢方法。
4.配置hystrix
在以前UserService上修改@FeignClient屬性如下:
@FeignClient(value = "microservicecloud-provider",fallbackFactory = UserServiceFallbackFactory.class)
5.測試
四、服務監控
hystrix除了應用於上述的服務熔斷和降級,還可以應用於服務的實時監控。Hystrix會持續地記錄所有通過Hystrix發起的請求的執行信息,並以統計報表和圖形的形式展示給用戶,包括每秒執行多少請求多少成功,多少失敗等。Netflix通過hystrix-metrics-event-stream項目實現了對以上指標的監控。Spring Cloud也提供了Hystrix Dashboard的整合,對監控內容轉化成可視化界面。
1.創建module
新建microservice-consumer-hystrix-dashbord模塊
2.添加依賴
<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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.syr.springcloud</groupId>
<artifactId>microservice</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>microservice-consumer-hystrix-dashbord8001</artifactId>
<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.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix-dashboard</artifactId>
</dependency>
<!-- 修改後立即生效,熱部署 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>springloaded</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
</dependencies>
</project>
3.配置信息
server:
port: 8001
4.開啓HystrixDashboard
@SpringBootApplication
@EnableHystrixDashboard
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
5.測試
http://localhost:8001/hystrix
:
啓動eureka集羣、microservice-provider-hystrix1004服務。
開啓監控後頁面如下:
6.測試發現
只有我在方法中用到hystrix熔斷,纔可以檢測,沒有用到的方法不能檢測。
7.檢測屬性
圖中的實心圓的顏色爲綠色,表示健康,健康程度排序綠色>黃色>橙色>紅色,綠色表示最健康,紅色表示最不健康。實心圓的大小表示了監控的服務訪問量的大小,訪問量越大,實心圓越大,反之,越小。圖中每個顏色數字表示如下: