1.Spring Cloud Hystrix簡介
(1).分布式問題
復雜分布式體系結構中的應用程式有數十個依賴關系,每個依賴關系在某些時候將不可避免地失敗,

多個微服務之間呼叫的時候,假設微服務A呼叫微服務B和微服務C,微服務B和微服務C又呼叫其它的微服務,這就是所謂的“扇出”,如果扇出的鏈路上某個微服務的呼叫回應時間過長或者不可用,對微服務A的呼叫就會占用越來越多的系統資源,進而引起系統崩潰,所謂的“雪崩效應”.
對于高流量的應用來說,單一的后端依賴可能會導致所有服務器上的所有資源都在幾秒鐘內飽和,比失敗更糟糕的是,這些應用程式還可能導致服務之間的延遲增加,備份佇列,執行緒和其他系統資源緊張,導致整個系統發生更多的級聯故障,這些都表示需要對故障和延遲進行隔離和管理,以便單個依賴關系的失敗,不能取消整個應用程式或系統,
備注:一般情況對于服務依賴的保護主要有3中解決方案:
①.熔斷模式:這種模式主要是參考電路熔斷,如果一條線路電壓過高,保險絲會熔斷,防止火災,放到我們的系統中,如果某個目標服務呼叫慢或者有大量超時,此時,熔斷該服務的呼叫,對于后續呼叫請求,不在繼續呼叫目標服務,直接回傳,快速釋放資源,如果目標服務情況好轉則恢復呼叫,
②.隔離模式:這種模式就像對系統請求按型別劃分成一個個小島的一樣,當某個小島被火少光了,不會影響到其他的小島,例如可以對不同型別的請求使用執行緒池來資源隔離,每種型別的請求互不影響,如果一種型別的請求執行緒資源耗盡,則對后續的該型別請求直接回傳,不再呼叫后續資源,這種模式使用場景非常多,例如將一個服務拆開,對于重要的服務使用單獨服務器來部署,再或者公司最近推廣的多中心,
③.限流模式:上述的熔斷模式和隔離模式都屬于出錯后的容錯處理機制,而限流模式則可以稱為預防模式,限流模式主要是提前對各個型別的請求設定最高的QPS閾值,若高于設定的閾值則對該請求直接回傳,不再呼叫后續資源,這種模式不能解決服務依賴的問題,只能解決系統整體資源分配問題,因為沒有被限流的請求依然有可能造成雪崩效應,
(2).Hystrix斷路器
Hystrix是一個用于處理分布式系統的延遲和容錯的開源庫,在分布式系統里,許多依賴不可避免的會呼叫失敗,比如超時、例外等,Hystrix能夠保證在一個依賴出問題的情況下,不會導致整體服務失敗,避免級聯故障,以提高分布式系統的彈性,
斷路器:本身是一種開關裝置,當某個服務單元發生故障之后,通過斷路器的故障監控(類似熔斷保險絲),向呼叫方回傳一個符合預期的、可處理的備選回應(FallBack),而不是長時間的等待或者拋出呼叫方無法處理的例外,這樣就保證了服務呼叫方的執行緒不會被長時間、不必要地占用,從而避免了故障在分布式系統中的蔓延,乃至雪崩,
(3).Hystrix作用
[1].服務降級
Hystrix服務降級,其實就是執行緒池中單個執行緒障處理,防止單個執行緒請求時間太長,導致資源長期被占有而得不到釋放,從而導致執行緒池被快速占用完,導致服務崩潰,
Hystrix能解決如下問題:
①.請求超時降級,執行緒資源不足降級,降級之后可以回傳自定義資料
②.執行緒池隔離降級,分布式服務可以針對不同的服務使用不同的執行緒池,從而互不影響
③.自動觸發降級與恢復
④.實作請求快取和請求合并
[2].服務熔斷
熔斷模式:這種模式主要是參考電路熔斷,如果一條線路電壓過高,保險絲會熔斷,防止火災,放到我們的系統中,如果某個目標服務呼叫慢或者有大量超時,此時,熔斷該服務的呼叫,對于后續呼叫請求,不在繼續呼叫目標服務,直接回傳,快速釋放資源,如果目標服務情況好轉則恢復呼叫,
[3].服務限流
限流模式主要是提前對各個型別的請求設定最高的QPS閾值,若高于設定的閾值則對該請求直接回傳,不再呼叫后續資源,這種模式不能解決服務依賴的問題,只能解決系統整體資源分配問題,因為沒有被限流的請求依然有可能造成雪崩效應,
[4].接近實時的監控
(4).官方檔案
https://github.com/Netflix/Hystrix/wiki/How-To-Use
2.服務熔斷

熔斷機制是應對雪崩效應的一種微服務鏈路保護機制,當扇出鏈路的某個微服務不可用或者回應時間太長時,會進行服務的降級,進而熔斷該節點微服務的呼叫,快速回傳"錯誤"的回應資訊,當檢測到該節點微服務呼叫回應正常后恢復呼叫鏈路,在SpringCloud框架里熔斷機制通過Hystrix實作,Hystrix會監控微服務間呼叫的狀況,當失敗的呼叫到一定閾值,預設是5秒內20次呼叫失敗就會啟動熔斷機制,熔斷機制的注解是@HystrixCommand,
(1).創建工程
新建microservicecloud-provider-dept-hystrix-8001


將microservicecloud-provider-dept-8001下的package和applicaiton.yml組態檔復制到microservicecloud-provider-dept-hystrix-8001上,

(2).配置pom檔案
修改部分:
|
<!-- hystrix --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-hystrix</artifactId> </dependency> |
完整部分:
|
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <parent> <artifactId>microservicecloud</artifactId> <groupId>com.hosystem</groupId> <version>1.0-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion>
<artifactId>microservicecloud-provider-dept-hystrix-8001</artifactId> <dependencies> <!-- 引入自己定義的api通用包,可以使用Dept部門Entity --> <dependency> <groupId>com.hosystem</groupId> <artifactId>microservicecloud-api</artifactId> <version>${project.version}</version> </dependency> <!-- 將微服務provider側注冊進eureka --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-config</artifactId> </dependency> <!-- actuator監控資訊完善 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> </dependency> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-core</artifactId> </dependency> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jetty</artifactId> </dependency> <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> </dependency> <!-- 修改后立即生效,熱部署 --> <dependency> <groupId>org.springframework</groupId> <artifactId>springloaded</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> </dependency> <!-- hystrix --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-hystrix</artifactId> </dependency> </dependencies>
</project> |
(3).修改applicaiton.yml
|
server: port: 8001
mybatis: config-location: classpath:mybatis/mybatis.cfg.xml # mybatis組態檔所在路徑 type-aliases-package: com.hosytem.springcloud.entities # 所有Entity別名類所在包 mapper-locations: - classpath:mybatis/mapper/**/*.xml # mapper映射檔案
#name spring.application.name=microservicecloud-dept 很重要很重要很重要 spring: application: name: microservicecloud-dept datasource: type: com.alibaba.druid.pool.DruidDataSource # 當前資料源操作型別 driver-class-name: org.gjt.mm.mysql.Driver # mysql驅動包 url: jdbc:mysql://192.168.188.188:3306/cloudDB01 # 資料庫名稱 username: root password: 123456 dbcp2: min-idle: 5 # 資料庫連接池的最小維持連接數 initial-size: 5 # 初始化連接數 max-total: 5 # 最大連接數 max-wait-millis: 200 # 等待連接獲取的最大超時時間
eureka: client: #客戶端注冊進eureka服務串列內 service-url: # defaultZone: http://localhost:7001/eureka defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/ instance: instance-id: microservicecloud-dept8001-hystrix #自定義服務名稱資訊 prefer-ip-address: true #訪問路徑可以顯示IP地址 info: app.name: hosystem-microservicecloud company.name: www.hosystem.com build.artifactId: $project.artifactId$ build.version: $project.version$ |
(4).修改DeptController

|
package com.hosystem.springcloud.controller;
import com.hosystem.springcloud.entities.Dept; import com.hosystem.springcloud.service.DeptService; import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.cloud.client.ServiceInstance; import org.springframework.cloud.client.discovery.DiscoveryClient; import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController public class DeptController {
@Autowired private DeptService service = null;
@RequestMapping(value="https://www.cnblogs.com/dept/get/{id}",method=RequestMethod.GET) //一旦呼叫服務方法失敗并拋出了錯誤資訊后,會自動呼叫@HystrixCommand標注好的fallbackMethod呼叫類中的指定方法 @HystrixCommand(fallbackMethod = "processHystrix_Get") public Dept get(@PathVariable("id") Long id) { Dept dept = this.service.get(id); if(null == dept) { throw new RuntimeException("該ID:"+id+"沒有沒有對應的資訊"); } return dept; }
public Dept processHystrix_Get(@PathVariable("id") Long id) { return new Dept().setDeptno(id) .setDname("該ID:"+id+"沒有沒有對應的資訊,null--@HystrixCommand") .setDb_source("no this database in MySQL"); } } |
(5).修改主啟動類
修改DeptProvider8001_App主啟動類,
|
package com.hosystem.springcloud;
import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
@SpringBootApplication @EnableEurekaClient //本服務啟動后會自動注冊進eureka服務中 @EnableDiscoveryClient @EnableCircuitBreaker//對hystrixR熔斷機制的支持 public class DeptProvider8001_Hystrix_App { public static void main(String[] args) { SpringApplication.run(DeptProvider8001_Hystrix_App.class, args); } } |
(6).測驗
[1].啟動eureka7001、eureka7002、eureka7003

[2].啟動DeptProvider8001_Hystrix_App

[3].啟動microservicecloud-consumer-dept-80


[4].訪問
|
http://localhost/consumer/dept/get/112 |

3.服務降級

整體資源不足于應對當前的困難,則選擇性關掉某些服務,優先提供重要的服務,
服務降級處理是在客戶端實作完成的,與服務端沒有關系,
(1).修改microservicecloud-api
修改microservicecloud-api工程,根據已經有的DeptClientService介面新建一個實作了FallbackFactory介面的類DeptClientServiceFallbackFactor,

|
package com.hosystem.springcloud.service;
import com.hosystem.springcloud.entities.Dept; import feign.hystrix.FallbackFactory; import org.springframework.stereotype.Component;
import java.util.List;
@Component//不要忘記添加,不要忘記添加 public class DeptClientServiceFallbackFactory implements FallbackFactory<DeptClientService> { @Override public DeptClientService create(Throwable throwable) { return new DeptClientService() { @Override public Dept get(long id) { return new Dept().setDeptno(id) .setDname("該ID:"+id+"沒有沒有對應的資訊,Consumer客戶端提供的降級資訊,此刻服務Provider已經關閉") .setDb_source("no this database in MySQL"); } @Override public List<Dept> list() { return null; } @Override public boolean add(Dept dept) { return false; } }; } } |
(2).修改DeptClientService介面
修改microservicecloud-api工程,DeptClientService介面在注解@FeignClient中添加fallbackFactory屬性值,

|
package com.hosystem.springcloud.service;
import com.hosystem.springcloud.entities.Dept; import org.springframework.cloud.netflix.feign.FeignClient; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod;
import java.util.List;
//@FeignClient(value = "https://www.cnblogs.com/HOsystem/p/MICROSERVICECLOUD-DEPT") @FeignClient(value = "https://www.cnblogs.com/HOsystem/p/MICROSERVICECLOUD-DEPT",fallbackFactory=DeptClientServiceFallbackFactory.class) public interface DeptClientService { @RequestMapping(value = "https://www.cnblogs.com/dept/get/{id}",method = RequestMethod.GET) public Dept get(@PathVariable("id") long id);
@RequestMapping(value = "https://www.cnblogs.com/dept/list",method = RequestMethod.GET) public List<Dept> list();
@RequestMapping(value = "https://www.cnblogs.com/dept/add",method = RequestMethod.POST) public boolean add(Dept dept); } |
(3).mvn clean和mvn install
對microservicecloud-api工程進行mvn clean install

(4).修改microservicecloud-consumer-dept-feign
microservicecloud-consumer-dept-feign工程修改YML
|
server: port: 80 feign: hystrix: enabled: true eureka: client: register-with-eureka: false service-url: defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/ |
(5).測驗
[1].啟動eureka7001、eureka7002、eureka7003
[2].啟動microservicecloud-provider-dept-8001
[3].啟動microservicecloud-consumer-dept-feign

[4].訪問測驗
①.正常測驗
|
http://localhost/consumer/dept/get/1 |

②.關閉服務測驗
關閉微服務microservicecloud-provider-dept-8001,
|
http://localhost/consumer/dept/get/1 |

此時服務端provider已經down了,但是我們做了服務降級處理,讓客戶端在服務端不可用時也會獲得提示資訊而不會掛起耗死服務器,
4.服務監控hystrixDashboard

除了隔離依賴服務的呼叫以外,Hystrix還提供了準實時的呼叫監控(Hystrix Dashboard),Hystrix會持續地記錄所有通過Hystrix發起的請求的執行資訊,并以統計報表和圖形的形式展示給用戶,包括每秒執行多少請求多少成功,多少失敗等,Netflix通過hystrix-metrics-event-stream專案實作了對以上指標的監控,Spring Cloud也提供了Hystrix Dashboard的整合,對監控內容轉化成可視化界面,
(1).新建工程
新建工程microservicecloud-consumer-hystrix-dashboard


(2).修改pom
修改部分:
|
<!-- hystrix和 hystrix-dashboard相關--> <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> |
完整部分:
|
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <parent> <artifactId>microservicecloud</artifactId> <groupId>com.hosystem</groupId> <version>1.0-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion>
<artifactId>microservicecloud-consumer-hystrix-dashboard</artifactId> <dependencies> <!-- 自己定義的api --> <dependency> <groupId>com.hosystem</groupId> <artifactId>microservicecloud-api</artifactId> <version>${project.version}</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency>
<!-- 修改后立即生效,熱部署 --> <dependency> <groupId>org.springframework</groupId> <artifactId>springloaded</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> </dependency>
<!-- Ribbon相關 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-ribbon</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-config</artifactId> </dependency>
<!-- feign相關 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-feign</artifactId> </dependency>
<!-- hystrix和 hystrix-dashboard相關--> <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> </dependencies> </project> |
(3).配置applicaiton.yml
|
server: port: 9001 |
(4).配置主啟動類
新建主啟動類DeptConsumer_DashBoard_App,然后添加注解@EnableHystrixDashboard.
|
package com.hosystem.springcloud;
import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.hystrix.dashboard.EnableHystrixDashboard;
@SpringBootApplication @EnableHystrixDashboard public class DeptConsumer_DashBoard_App { public static void main(String[] args) { SpringApplication.run(DeptConsumer_DashBoard_App.class,args); } } |
(5).配置provider監控依賴
所有Provider微服務提供類(8001/8002/8003)都需要監控依賴配置.
|
<!-- actuator監控資訊完善 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> |
(6).啟動專案
[1].啟動dashboard
啟動microservicecloud-consumer-hystrix-dashboard該微服務監控消費端,
|
http://localhost:9001/hystrix |

[2].啟動eureka
啟動eureka7001、eureka7002、eureka7003

[3].啟動hystrix
啟動microservicecloud-provider-dept-hystrix-8001

|
http://localhost:8001/dept/get/1 http://localhost:8001/hystrix.stream |

(7).監控測驗
多次重繪http://localhost:8001/dept/get/1,然后通過Hystrix Dashboard查看,
[1].填寫監控地址
|
http://localhost:8001/hystrix.stream |

Delay:該引數用來控制服務器上輪詢監控資訊的延遲時間,默認為2000毫秒,可以通過配置該屬性來降低客戶端的網路和CPU消耗,
Title:該引數對應了頭部標題Hystrix Stream之后的內容,默認會使用具體監控實體的URL,可以通過配置該資訊來展示更合適的標題,
[2].監控結果
7色、1圈、1線

實心圓:共有兩種含義,它通過顏色的變化代表了實體的健康程度,它的健康度從綠色<黃色<橙色<紅色遞減,該實心圓除了顏色的變化之外,它的大小也會根據實體的請求流量發生變化,流量越大該實心圓就越大,所以通過該實心圓的展示,就可以在大量的實體中快速的發現故障實體和高壓力實體
曲線:用來記錄2分鐘內流量的相對變化,可以通過它來觀察到流量的上升和下降趨勢,

[3].復雜監控結果

參考檔案:
https://github.com/Netflix/Hystrix/wiki/How-To-Use
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/232869.html
標籤:Java



