Hystrix断路器(五)
?
1.1.1????? 概念
大意是一個系統依賴30個微服務,假設每個微服務可用時間是99.99%,換算成整個系統就是99.99的30次方約99.7%可用時間,0.3%不可用。1億的請求有30萬失敗。30天有2個多小時不能正常提供服務。
現實通常比這更糟糕。舉個例子:假設我們在電商網站買東西,從下單到完成要依賴三個微服務:訂單、支付、物流。遇上雙11或618,客戶的訂單蜂擁而至,這時候物流微服務可能因為程序優化不好或者硬件資源不夠而不能及時提供服務,如果因為物流的問題而導致客戶無法下單,這到手的錢掙不到了就很可惜了。
這時候就可以對物流微服務進行熔斷,暫時不調用,全力以赴把訂單、支付給完成了。熬過去這段峰值,回過頭來再處理物流的問題,反正錢已到手。不會因為一顆老鼠屎壞一鍋湯。
Spring Cloud的斷路器是Hystrix,兩種使用方法,一種是直接使用Hystrix,一種是通過FeignClient。
1.1.2????? 微服務設計引發新的問題
微服務的設計,服務分散在多個服務器上,服務之間互相調用,要調用的服務由于跨網絡跨服務器調用,響應速度明顯比傳統項目單機調用慢很多,甚至由于網絡涌動的不穩定的現象發生導致調用超時;還有類似級聯失敗、雪崩效應(依賴的基礎服務宕機,關聯的服務導致失敗甚至宕機,就像滾雪球一樣層層失敗。)
?
如何解決這類新的問題呢?傳統的機制就是超時機制。
1.1.3????? 超時機制
良好的設計,在通過網絡請求其他服務時,都必須設置超時時間。正常情況下,一個遠程調用幾十毫秒內返回。當要調用的服務不可用時或者網絡問題,響應時間要等超時,如HttpClient幾十秒才超時返回。通常,一次遠程調用對應一個線程/進程,如果大量的線程/進程得不到釋放,并且越積越多,服務資源就會被耗盡,從而導致資深服務不可用。所以必須為每個請求設置超時時間。
例如:我們熟悉的tomcat就有超時設計
<Connector port="8080" protocol="HTTP/1.1"
???????????? ?connectionTimeout="20000"
????????????? redirectPort="8443" acceptCount="500" maxThreads="400" />
但我們發現傳統的超時設計時間都比較久,面對今天互聯網時代,用戶對性能的極致要求時間顯得太久了?20秒,用戶要求網頁秒級響應,等20秒,用戶只能跟你說byebye了,扭頭去找別的提供商了。
特別像微服務這樣基于多個服務,服務之間都是遠程調用,如果一個服務長時間等待,用戶體驗會極差的,那怎么辦呢?斷路器模式應運而生。
1.1.4????? 熔斷機制
家里電表都有個斷路器(俗稱電閘),當使用的電器很多,用電巨大(例如功率過大、短路等),當電流過載時,電路就會升溫,甚至燒斷電路,引起火災。有了這個斷路器,我們及時拉閘,就不會造成嚴重后果了。
斷路器可以實現快速失敗,如果它在一段時間內檢測到許多失敗,如超時,就會強迫其以后的多個調用快速失敗,不再請求所依賴的服務,從而防止應用程序不斷地嘗試執行可能會失敗的操作,這樣應用程序可以繼續執行而不用等待修正錯誤,或者浪費CPU時間去等待長時間的超時。斷路器也可以使應用程序能夠診斷錯誤是否已經修正,如果已經修正,應用程序會再次嘗試調用操作。
斷路器模式像是那些容易導致錯誤的操作的一種代理。這種代理能夠記錄最近調用發生錯誤的次數,然后決定使用允許操作繼續,或者立即返回錯誤。
1.1.5????? 狀態
?
斷路器有三種狀態:
1.??? 關閉:當訪問沒有問題時,斷路器處于關閉未使用。
2.??? 打開:當訪問開始出現異常,錯誤次數增多,達到閥值時就會打開斷路器,這樣服務直接訪問斷路器,斷路器會再嘗試訪問,如果失敗直接返回。
3.??? 半開:那服務一直走斷路器,系統就沒法用了,萬一被調用的服務以及穩定了呢。斷路器的優勢就來了,過一定時間窗口后(若干秒)它就會自動分流一部分服務再去嘗試訪問之前失敗的服務。如果繼續失敗,那就不再轉發,如果一個成功立即關閉斷路器。
1.1.6????? 結構圖
?
當服務B不可用時,開發人員需要寫一個Fallback快速失敗響應。可以設置為一個固定的值或者一個空值。
Hystrix默認的超時時間是1秒,如果超過這個時間尚未響應,將會進入fallback代碼。而首次請求往往會比較慢(因為Spring的懶加載機制,要實例化一些類),這個響應時間可能就大于1秒了。
1.1.7????? 小結
l?不是立即宣布死亡,而是設置閥值,超越閥值才宣布死亡
l?傳統方式死亡了就不管了,可斷路器超級厲害,“死了也不放過”。自帶心跳機制,自動測試路徑是否可用,如發現又“活了”,會自動恢復調用關系。這一切開發者都無需編寫代碼
這樣的設計太牛了,考慮非常細致全面,可以說做到了極致。不可用時立即響應,可用時自動恢復。不是網絡抖動下,就永遠宣布其死亡。這樣的設計思想非常適合網絡這種不穩定的應用場景。
1.2???????? 消費者實現Hystrix
1.2.1????? 創建Maven項目
?
1.2.2????? pom.xml
增加hystrix依賴
<?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">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.wood</groupId>
<artifactId>spring-cloud</artifactId>
<version>0.0.1-SNAPSHOT</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.wood</groupId>
<artifactId>consumer-hystrix</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>consumer-hystrix</name>
<description>Demo project for Spring Boot</description>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<!-- Feign依賴,聲明式開發 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-feign</artifactId>
<version>LATEST</version>
</dependency>
<!-- Hystrix,Feign是基于Hystrix的,Hystrix下一章節會講到 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
<version>LATEST</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix-dashboard</artifactId>
<version>LATEST</version>
</dependency>
</dependencies>
</project>
?
1.2.3????? 導入hystrix支持
Spring cloud沒有直接使用NetFlix開源的Hystrix,而使用的是javanica,javanica在Hystrix基礎上利用反射和注解技術增強和簡化了Hystrix的開發。
1.2.4????? application.properties
?
server.port=8094spring.application.name=consumer-hystrix
eureka.client.serviceUrl.defaultZone=http://localhost:6001/eureka
# 定義根目錄下日志級別
logging.level.root=INFO
# 放開 hystrix 、health、info 等功能
management.endpoints.web.exposure.include="*"
1.2.5????? EurekaServiceFeign.java
?
package com.wood.consumerhystrix.remote;import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
/**
* 這個接口相當于把原來的服務提供者項目當成一個Service類
**/
@FeignClient(value="provider-user", fallback = UserFeignFallback.class)
public interface EurekaServiceFeign {
/**
* Feign中沒有原生的@GetMapping/@PostMapping/@DeleteMapping/@PutMapping
* 要指定需要用method進行
* */
@RequestMapping(value="/hello/{name}",method=RequestMethod.GET)
String hello(@PathVariable("name") String name);
}
?
1.2.6????? HelloController.java
package com.wood.consumerhystrix.controller;import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.wood.consumerhystrix.remote.EurekaServiceFeign;
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.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HelloController {
@Autowired
private EurekaServiceFeign eurekaServiceFeign;
/**
* hystrix配合feign使用
* 當feign連接出現故障,就不會再去請求了,直接進入fallback
* tip:默認開啟了兩個provider-user服務,每次訪問時交替出現,feign自帶負載均衡的功能
* 如果滿足不了需求可以加上Ribbon來實現專業的負載均衡
* @RibbonClient(name="provider-user", configuration=RibbonRuleConfig.class)
* */
@GetMapping("/hello/{name}")
@ResponseBody
@HystrixCommand(fallbackMethod = "helloFallback")
public String hello(@PathVariable String name){
return eurekaServiceFeign.hello(name);
}
// 對應上面的方法,參數必須一致當訪問失敗時,hystrix直接回調用此方法
public String helloFallback(String name) {
return name + "\nhystrix配合feign使用,當feign連接出現故障,就不會再去請求了,直接進入fallback";
}
}
?
1.2.7????? HystrixRunApp.java
?
package com.wood.consumerhystrix;import com.netflix.hystrix.contrib.metrics.eventstream.HystrixMetricsStreamServlet;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.hystrix.EnableHystrix;
import org.springframework.cloud.netflix.hystrix.dashboard.EnableHystrixDashboard;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.context.annotation.Bean;
@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients //開啟feign
@EnableCircuitBreaker //開啟hystrix
@EnableHystrixDashboard
@EnableHystrix // spring cloud 2.x hystrix沒有/actuator/hystrix.stream路徑解決
public class ConsumerHystrixApplication {
public static void main(String[] args) {
SpringApplication.run(ConsumerHystrixApplication.class, args);
}
// spring cloud 2.x hystrix沒有/actuator/hystrix.stream路徑解決
@Bean
public ServletRegistrationBean getServlet(){
HystrixMetricsStreamServlet streamServlet = new HystrixMetricsStreamServlet();
ServletRegistrationBean registrationBean = new ServletRegistrationBean(streamServlet);
registrationBean.setLoadOnStartup(1);
registrationBean.addUrlMappings("/actuator/hystrix.stream");
registrationBean.setName("HystrixMetricsStreamServlet");
return registrationBean;
}
}
?
1.2.8????? 測試
執行順序:
先啟動服務端 ? ?6001? ? eureka-server? ? ? ? ? ? ? ??
在啟動提供者1?? 8081? ? provider-user? ? ? ? ? ? ? ??
最后啟動消費者?? 8094? ? consumer-hystrix??
?
訪問Eureka控制臺:????? http://localhost:6001/
?
訪問請求:?????????????? http://localhost:8094/hello/hi
?
注意:可能訪問太快時第一次就出現斷路器實現,這時訪問太快,服務還未生效,多刷新幾次,業務正常時應該出現上面的提示。
1.2.9????? 測試斷路器
關閉provider-user,模擬服務失敗宕機場景。
?
訪問請求:?????? http://localhost:8094/hello/hi
?
可以看到已經走了fallback方法。
?
重啟provider-user服務,模擬服務修復,可以看到立即返回正確結果,說明服務正常時不會走斷路器方法。
?
設置斷點,和我們預想的相同,會發現只有異常時才走斷路器的回調方法。
1.3???????? 拓展:HystrixDashBoard
1.3.1????? 需要依賴jar包支持
只針對當前實例,actuator是SpringBoot提供的一些監控的擴展支持
??? <dependency>
???????????? <groupId>org.springframework.boot</groupId>
???????????? <artifactId>spring-boot-starter-actuator</artifactId>
??? </dependency>
1.3.2????? pom.xml
<dependency><groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix-dashboard</artifactId>
<version>LATEST</version>
</dependency>
?
1.3.3????? HystrixRunApp.java
?
@EnableHystrixDashboard@EnableHystrix // spring cloud 2.x hystrix沒有/actuator/hystrix.stream路徑解決// spring cloud 2.x hystrix沒有/actuator/hystrix.stream路徑解決
@Bean
public ServletRegistrationBean getServlet(){
HystrixMetricsStreamServlet streamServlet = new HystrixMetricsStreamServlet();
ServletRegistrationBean registrationBean = new ServletRegistrationBean(streamServlet);
registrationBean.setLoadOnStartup(1);
registrationBean.addUrlMappings("/actuator/hystrix.stream");
registrationBean.setName("HystrixMetricsStreamServlet");
return registrationBean;
}
?
1.3.4????? 查看監控日志
訪問鏈接:http://localhost:8094/hystrix
?
居然是404,為什么呢,spring-cloud 1.x 是OK的,但2.x不能訪問
# 放開 hystrix 、health、info 等功能management.endpoints.web.exposure.include="*" @EnableCircuitBreaker //開啟hystrix
@EnableHystrixDashboard
@EnableHystrix // spring cloud 2.x hystrix沒有/actuator/hystrix.stream路徑解決 // spring cloud 2.x hystrix沒有/actuator/hystrix.stream路徑解決
@Bean
public ServletRegistrationBean getServlet(){
HystrixMetricsStreamServlet streamServlet = new HystrixMetricsStreamServlet();
ServletRegistrationBean registrationBean = new ServletRegistrationBean(streamServlet);
registrationBean.setLoadOnStartup(1);
registrationBean.addUrlMappings("/actuator/hystrix.stream");
registrationBean.setName("HystrixMetricsStreamServlet");
return registrationBean;
}
訪問8094,消費者鏈接,展示ping:一直打印,轉個不停。
訪問一次業務 http://localhost:8094/hello/hi
停止提供者,刷新消費者,開始打印日志信息
?
可以基于控制臺訪問(http://localhost:8094/hystrix)
?
輸入鏈接:http://localhost:8094/actuator/hystrix.stream,點擊monitor按鈕
?
具體指標的含義為:
?
?
在監控的界面有兩個重要的圖形信息:一個實心圓和一條曲線。
l?實心圓:
1、通過顏色的變化代表了實例的健康程度,健康程度從綠色、黃色、橙色、紅色遞減。
2、通過大小表示請求流量發生變化,流量越大該實心圓就越大。所以可以在大量的實例中快速發現故障實例和高壓實例。
l?曲線:用來記錄2分鐘內流浪的相對變化,可以通過它來觀察流量的上升和下降趨勢。
?
提供demo下載
spring-cloud-hystrix.zip?
?
?
轉載于:https://www.cnblogs.com/wood-life/p/10340602.html
總結
以上是生活随笔為你收集整理的Hystrix断路器(五)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: JavaWeb-SpringBoot_一
- 下一篇: js中的构造函数