敘述一個網(wǎng)站開發(fā)流程/廣州seo優(yōu)化效果
8. Hystrix:服務(wù)熔斷
分布式系統(tǒng)面臨的問題
復(fù)雜分布式體系結(jié)構(gòu)中的應(yīng)用程序有數(shù)十個依賴關(guān)系,每個依賴關(guān)系在某些時候?qū)⒉豢杀苊馐?#xff01;
8.1 服務(wù)雪崩
多個微服務(wù)之間調(diào)用的時候,假設(shè)微服務(wù)A調(diào)用微服務(wù)B和微服務(wù)C,微服務(wù)B和微服務(wù)C又調(diào)用其他的微服務(wù),這就是所謂的“扇出”,如果扇出的鏈路上某個微服務(wù)的調(diào)用響應(yīng)時間過長,或者不可用,對微服務(wù)A的調(diào)用就會占用越來越多的系統(tǒng)資源,進而引起系統(tǒng)崩潰,所謂的“雪崩效應(yīng)”。
對于高流量的應(yīng)用來說,單一的后端依賴可能會導(dǎo)致所有服務(wù)器上的所有資源都在幾十秒內(nèi)飽和。比失敗更糟糕的是,這些應(yīng)用程序還可能導(dǎo)致服務(wù)之間的延遲增加,備份隊列,線程和其他系統(tǒng)資源緊張,導(dǎo)致整個系統(tǒng)發(fā)生更多的級聯(lián)故障,這些都表示需要對故障和延遲進行隔離和管理,以達到單個依賴關(guān)系的失敗而不影響整個應(yīng)用程序或系統(tǒng)運行。
我們需要,棄車保帥!
8.2 什么是Hystrix?
Hystrix是一個應(yīng)用于處理分布式系統(tǒng)的延遲和容錯的開源庫,在分布式系統(tǒng)里,許多依賴不可避免的會調(diào)用失敗,比如超時,異常等,Hystrix 能夠保證在一個依賴出問題的情況下,不會導(dǎo)致整個體系服務(wù)失敗,避免級聯(lián)故障,以提高分布式系統(tǒng)的彈性。
“斷路器”本身是一種開關(guān)裝置,當某個服務(wù)單元發(fā)生故障之后,通過斷路器的故障監(jiān)控 (類似熔斷保險絲) ,向調(diào)用方返回一個服務(wù)預(yù)期的,可處理的備選響應(yīng) (FallBack) ,而不是長時間的等待或者拋出調(diào)用方法無法處理的異常
,**這樣就可以保證了服務(wù)調(diào)用方的線程不會被長時間,不必要的占用,**從而避免了故障在分布式系統(tǒng)中的蔓延,乃至雪崩。
8.3 Hystrix能干嘛?
- 服務(wù)降級
- 服務(wù)熔斷
- 服務(wù)限流
- 接近實時的監(jiān)控
- …
當一切正常時,請求流可以如下所示:
當許多后端系統(tǒng)中有一個潛在阻塞服務(wù)時,它可以阻止整個用戶請求:
隨著大容量通信量的增加,單個后端依賴項的潛在性會導(dǎo)致所有服務(wù)器上的所有資源在幾秒鐘內(nèi)飽和。
應(yīng)用程序中通過網(wǎng)絡(luò)或客戶端庫可能導(dǎo)致網(wǎng)絡(luò)請求的每個點都是潛在故障的來源。比失敗更糟糕的是,這些應(yīng)用程序還可能導(dǎo)致服務(wù)之間的延遲增加,從而備份隊列、線程和其他系統(tǒng)資源,從而導(dǎo)致更多跨系統(tǒng)的級聯(lián)故障。
當使用Hystrix包裝每個基礎(chǔ)依賴項時,上面的圖表中所示的體系結(jié)構(gòu)會發(fā)生類似于以下關(guān)系圖的變化。每個依賴項是相互隔離的,限制在延遲發(fā)生時它可以填充的資源中,并包含在回退邏輯中,該邏輯決定在依賴項中發(fā)生任何類型的故障時要做出什么樣的響應(yīng):
官網(wǎng)資料:https://github.com/Netflix/Hystrix/wiki
8.4 服務(wù)熔斷(服務(wù)端)
什么是服務(wù)熔斷?
熔斷機制是賭贏雪崩效應(yīng)的一種微服務(wù)鏈路保護機制。
當扇出鏈路的某個微服務(wù)不可用或者響應(yīng)時間太長時,會進行服務(wù)的降級,進而熔斷該節(jié)點微服務(wù)的調(diào)用,快速返回錯誤的響應(yīng)信息。檢測到該節(jié)點微服務(wù)調(diào)用響應(yīng)正常后恢復(fù)調(diào)用鏈路。在SpringCloud框架里熔斷機制通過Hystrix實現(xiàn)。Hystrix會監(jiān)控微服務(wù)間調(diào)用的狀況,當失敗的調(diào)用到一定閥值缺省是5秒內(nèi)20次調(diào)用失敗,就會啟動熔斷機制。熔斷機制的注解是:@HystrixCommand
。
服務(wù)熔斷解決如下問題:
- 當所依賴的對象不穩(wěn)定時,能夠起到快速失敗的目的;
- 快速失敗后,能夠根據(jù)一定的算法動態(tài)試探所依賴對象是否恢復(fù)。
入門案例
1、新建springcloud-provider-dept-hystrix-8001模塊并拷貝springcloud-provider-dept–8001內(nèi)的pom.xml、resource和Java代碼進行初始化并調(diào)整。
2、調(diào)整yml配置文件
3、導(dǎo)入 hystrix依賴
<!--導(dǎo)入Hystrix依賴-->
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-hystrix</artifactId><version>1.4.6.RELEASE</version>
</dependency>
4、理解注解@HystrCommand,知道它可以配置哪些屬性
5、改造DeptController
//提供Restful服務(wù)
@RestController
public class DeptController {@Autowiredprivate DeptService deptService;/*** 根據(jù)id查詢部門信息* 如果根據(jù)id查詢出現(xiàn)異常,則走hystrixGet這段備選代碼* @param id* @return*/@HystrixCommand(fallbackMethod = "hystrixGet")@RequestMapping("/dept/get/{id}")//根據(jù)id查詢public Dept get(@PathVariable("id") Long id){Dept dept = deptService.queryById(id);if (dept==null){throw new RuntimeException("這個id=>"+id+",不存在該用戶,或信息無法找到~");}return dept;}/*** 根據(jù)id查詢備選方案(熔斷)* @param id* @return*/public Dept hystrixGet(@PathVariable("id") Long id){return new Dept().setDeptno(id).setDname("這個id=>"+id+",沒有對應(yīng)的信息,null---@Hystrix~").setDb_source("在MySQL中沒有這個數(shù)據(jù)庫");}
}
上面的異常方法和備選方法的實現(xiàn)的效果理論上一樣,但是捕獲異常的容易因為延遲和其它情況崩掉,備選方案一直都可以使用
6、在啟動類上開啟對熔斷的支持@EnableCircuitBreaker
@SpringBootApplication
@EnableEurekaClient // EnableEurekaClient 客戶端的啟動類,在服務(wù)啟動后自動向注冊中心注冊服務(wù)
@EnableDiscoveryClient // 服務(wù)發(fā)現(xiàn)~
@EnableCircuitBreaker // 添加對熔斷的支持注解
public class HystrixDeptProvider_8001 {public static void main(String[] args) {SpringApplication.run(HystrixDeptProvider_8001.class,args);}
}
7、測試1:
熔斷機制的備選方案
8、將之前的自定義負載均衡的算法改成輪詢算法,再測試
同時測試在不使用hystrix的時候,出現(xiàn)崩掉的情況
熔斷機制就是為了預(yù)防這種情況,異常拋出有延遲
9、修改服務(wù)IP地址
**prefer-ip-address: true: **
因此,為了避免因某個微服務(wù)后臺出現(xiàn)異?;蝈e誤而導(dǎo)致整個應(yīng)用或網(wǎng)頁報錯,使用熔斷是必要的
8.5 服務(wù)降級(客戶端)
1.什么是服務(wù)降級?
服務(wù)降級是指 當服務(wù)器壓力劇增的情況下,根據(jù)實際業(yè)務(wù)情況及流量,對一些服務(wù)和頁面有策略的不處理,或換種簡單的方式處理,從而釋放服務(wù)器資源以保證核心業(yè)務(wù)正常運作或高效運作。說白了,**就是盡可能的把系統(tǒng)資源讓給優(yōu)先級高的服務(wù)**
。
**資源有限,而請求是無限的。**如果在并發(fā)高峰期,不做服務(wù)降級處理,一方面肯定會影響整體服務(wù)的性能,嚴重的話可能會導(dǎo)致宕機某些重要的服務(wù)不可用。所以,一般在高峰期,為了保證核心功能服務(wù)的可用性,都要對某些服務(wù)降級處理。比如當雙11活動時,把交易無關(guān)的服務(wù)統(tǒng)統(tǒng)降級,如查看螞蟻深林,查看歷史訂單等等。
服務(wù)降級主要用于什么場景呢?當整個微服務(wù)架構(gòu)整體的負載超出了預(yù)設(shè)的上限閾值或即將到來的流量預(yù)計將會超過預(yù)設(shè)的閾值時,為了保證重要或基本的服務(wù)能正常運行,可以將一些 不重要 或 不緊急 的服務(wù)或任務(wù)進行服務(wù)的 延遲使用 或 暫停使用。
降級的方式可以根據(jù)業(yè)務(wù)來,可以延遲服務(wù),比如延遲給用戶增加積分,只是放到一個緩存中,等服務(wù)平穩(wěn)之后再執(zhí)行 ;或者在粒度范圍內(nèi)關(guān)閉服務(wù),比如關(guān)閉相關(guān)文章的推薦。
由上圖可得,當某一時間內(nèi)服務(wù)A的訪問量暴增,而B和C的訪問量較少,為了緩解A服務(wù)的壓力,這時候需要B和C暫時關(guān)閉一些服務(wù)功能,去承擔(dān)A的部分服務(wù),從而為A分擔(dān)壓力,叫做服務(wù)降級。
2.服務(wù)降級需要考慮的問題
- 1)那些服務(wù)是核心服務(wù),哪些服務(wù)是非核心服務(wù)
- 2)那些服務(wù)可以支持降級,那些服務(wù)不能支持降級,降級策略是什么
- 3)除服務(wù)降級之外是否存在更復(fù)雜的業(yè)務(wù)放通場景,策略是什么?
3.自動降級分類
1)超時降級:主要配置好超時時間和超時重試次數(shù)和機制,并使用異步機制探測回復(fù)情況
2)失敗次數(shù)降級:主要是一些不穩(wěn)定的api,當失敗調(diào)用次數(shù)達到一定閥值自動降級,同樣要使用異步機制探測回復(fù)情況
3)故障降級:比如要調(diào)用的遠程服務(wù)掛掉了(網(wǎng)絡(luò)故障、DNS故障、http服務(wù)返回錯誤的狀態(tài)碼、rpc服務(wù)拋出異常),則可以直接降級。降級后的處理方案有:默認值(比如庫存服務(wù)掛了,返回默認現(xiàn)貨)、兜底數(shù)據(jù)(比如廣告掛了,返回提前準備好的一些靜態(tài)頁面)、緩存(之前暫存的一些緩存數(shù)據(jù))
4)限流降級:秒殺或者搶購一些限購商品時,此時可能會因為訪問量太大而導(dǎo)致系統(tǒng)崩潰,此時會使用限流來進行限制訪問量,當達到限流閥值,后續(xù)請求會被降級;降級后的處理方案可以是:排隊頁面(將用戶導(dǎo)流到排隊頁面等一會重試)、無貨(直接告知用戶沒貨了)、錯誤頁(如活動太火爆了,稍后重試)。
4.入門案例
(1)在springcloud-api模塊下的service包中新建降級配置類DeptClientServiceFallBackFactory.java
@Component
public class DeptClientServiceFallBackFactory implements FallbackFactory {@Overridepublic DeptClientService create(Throwable cause) {return new DeptClientService() {@Overridepublic Dept queryById(Long id) {return new Dept().setDeptno(id).setDname("id=>" + id + "沒有對應(yīng)的信息,客戶端提供了降級的信息,這個服務(wù)現(xiàn)在已經(jīng)被關(guān)閉").setDb_source("沒有數(shù)據(jù)~");}@Overridepublic List<Dept> queryAll() {return null;}@Overridepublic Boolean addDept(Dept dept) {return false;}};}
}
(2)分析注解FeignClient的源碼可知
設(shè)置一些屬性值就可以了
(3) 在DeptClientService中指定降級配置類DeptClientServiceFallBackFactory
(4) 在springcloud-consumer-dept-feign模塊中開啟降級:
參照導(dǎo)入的包名
設(shè)置降級
server:port: 80# Eureka配置
eureka:client:register-with-eureka: false # 不向 Eureka注冊自己service-url: # 從三個注冊中心中隨機取一個去訪問defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/# 開啟降級feign.hystrix
feign:hystrix:enabled: true
(5)測試效果:
先開啟服務(wù)注冊中心7001、7002Eureka,接著開啟服務(wù)提供者8001,再開啟服務(wù)消費者Feign,可以正常訪問
當關(guān)閉服務(wù)提供者8001,即:服務(wù)關(guān)閉了后,再訪問服務(wù)器請求服務(wù),服務(wù)器已經(jīng)無法訪問,但是客戶端設(shè)置的Feign提供的服務(wù)降級功能,會返回客戶端的消息:服務(wù)器無法調(diào)用了服務(wù)了
8.6 服務(wù)熔斷和降級的區(qū)別
- 服務(wù)熔斷—>服務(wù)端:
某個服務(wù)超時或異常,引起熔斷~,類似于保險絲(自我熔斷)
- 服務(wù)降級—>客戶端:
從整體網(wǎng)站請求負載考慮,當某個服務(wù)熔斷或者關(guān)閉之后,服務(wù)將不再被調(diào)用,此時在客戶端,我們可以準備一個 FallBackFactory ,返回一個默認的值(缺省值)。會導(dǎo)致整體的服務(wù)下降,但是好歹能用,比直接掛掉強。
- ①觸發(fā)原因不太一樣,
服務(wù)熔斷一般是某個服務(wù)(下游服務(wù))故障引起,而服務(wù)降級一般是從整體負荷考慮
;②管理目標的層次不太一樣,熔斷其實是一個框架級的處理,每個微服務(wù)都需要(無層級之分),而降級一般需要對業(yè)務(wù)有層級之分(比如降級一般是從最外圍服務(wù)開始)
- ③實現(xiàn)方式不太一樣,
服務(wù)降級具有代碼侵入性(由控制器完成/或自動降級),熔斷一般稱為自我熔斷
。
熔斷,降級,限流:
限流:限制并發(fā)的請求訪問量,超過閾值則拒絕;
降級:服務(wù)分優(yōu)先級,犧牲非核心服務(wù)(不可用),保證核心服務(wù)穩(wěn)定;從整體負荷考慮;
熔斷:依賴的下游服務(wù)故障觸發(fā)熔斷,避免引發(fā)本系統(tǒng)崩潰;系統(tǒng)自動執(zhí)行和恢復(fù)
8.7 Dashboard 流監(jiān)控
新建springcloud-consumer-hystrix-dashboard模塊
1.添加依賴
除了和80的POM文件的依賴一樣,還需要增加 hystrix 和 hystrix -dashboard 的依賴,同時3個服務(wù)提供者8001、8002、8003都需要添加完善監(jiān)控的actuator依賴
<!--Hystrix依賴-->
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-hystrix</artifactId><version>1.4.6.RELEASE</version>
</dependency>
<!--dashboard依賴-->
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-hystrix-dashboard</artifactId><version>1.4.6.RELEASE</version>
</dependency>
<!--Ribbon-->
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-ribbon</artifactId><version>1.4.6.RELEASE</version>
</dependency>
<!--Eureka-->
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-eureka</artifactId><version>1.4.6.RELEASE</version>
</dependency>
<!--實體類+web-->
<dependency><groupId>com.haust</groupId><artifactId>springcloud-api</artifactId><version>1.0-SNAPSHOT</version>
</dependency>
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--熱部署-->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-devtools</artifactId>
</dependency>
2.配置springcloud-consumer-hystrix-dashboard的端口
3.主啟動類
開啟監(jiān)控
@SpringBootApplication
// 開啟Dashboard
@EnableHystrixDashboard
public class DeptConsumerDashboard_9001 {public static void main(String[] args) {SpringApplication.run(DeptConsumerDashboard_9001.class,args);}
}
4.測試:先啟動9001的, 訪問:http://localhost:9001/hystrix
5. 給springcloud-provider-dept-hystrix-8001模塊下的主啟動類添加如下代碼,添加監(jiān)控
@SpringBootApplication
@EnableEurekaClient //EnableEurekaClient 客戶端的啟動類,在服務(wù)啟動后自動向注冊中心注冊服務(wù)
public class DeptProvider_8001 {public static void main(String[] args) {SpringApplication.run(DeptProvider_8001.class,args);}//增加一個 Servlet@Beanpublic ServletRegistrationBean hystrixMetricsStreamServlet(){ServletRegistrationBean registrationBean = new ServletRegistrationBean(new HystrixMetricsStreamServlet());//訪問該頁面就是監(jiān)控頁面registrationBean.addUrlMappings("/actuator/hystrix.stream");return registrationBean;}
}
6.再次啟動測試
先啟動7001–>hystrix-8001–>dashboard9001
訪問:localhost:8001/actuator/hystrix.stream
輸入所要監(jiān)控服務(wù)的信息,進行監(jiān)控,效果如圖:
本質(zhì)上監(jiān)控請求的信息
SpringCloud-Hystrix:服務(wù)熔斷與服務(wù)降級 到此完結(jié),筆者歸納、創(chuàng)作不易,大佬們給個3連再起飛吧