一、概述
1、分布式系統面臨的問題
複雜分布式體系結構中的應用程式有數十個依賴關系,每個依賴關系在某些時候将不可避免的失敗!
2、服務雪崩
多個微服務之間調用的時候,假設微服務A調用微服務B和微服務C,微服務B 和微服務C又調用其他的微服務,這就是所謂的 “扇出”、如果扇出的鍊路上某個微服務的調用響應時間過長或者不可用,對微服務A的調用就會占用越來越多的系統資源,進而引起系統崩潰,所謂的 “雪崩效應”。
對于高流量的應用來說,單一的後端依賴可能會導緻所有伺服器上的所有資源都在幾秒中内飽和。比失敗更糟糕的是,這些應用程式還可能導緻服務之間的延遲增加,備份隊列,線程和其他系統資源緊張,導緻整個系統發生更多的級聯故障,這些都表示需要對故障和延遲進行隔離和管理,以便單個依賴關系的失敗,不能取消整個應用程式或系統。
我們需要 ·棄車保帥·
3、什麼是Hystrix
Hystrix是一個用于處理分布式系統的延遲和容錯的開源庫,在分布式系統裡,許多依賴不可避免的會調用失敗,比如逾時,異常等,Hystrix能夠保證在一個依賴出問題的情況下,不會導緻整體服務失敗,避免級聯故障,以提高分布式系統的彈性。
“斷路器” 本身是一種開關裝置,當某個服務單元發生故障之後,通過斷路器的故障監控(類似熔斷保險絲),向調用方傳回一個服務預期的,可處理的備選響應(FallBack),而不是長時間的等待或者抛出調用方法無法處理的異常,這樣就可以保證了服務調用方的線程不會被長時間,不必要的占用,進而避免了故障在分布式系統中的蔓延,乃至雪崩。
4、Hystrix能幹嘛
- 服務熔斷
- 服務降級
- 服務限流
- 接近實時的監控
- … …
5、官網資料
https://github.com/Netflix/Hystrix/wiki
二、服務熔斷
1、是什麼?
熔斷機制是對應雪崩效應的一種微服務鍊路保護機制。
當扇對外連結路的某個微服務不可用或者響應時間太長時,會進行服務的降級,進而熔斷該節點微服務的調用,快速傳回 錯誤的響應資訊。當檢測到該節點微服務調用響應正常後恢複調用鍊路。在SpringCloud架構裡熔斷機制通過Hystrix實作。Hystrix會監控微服務間調用的狀況,當失敗的調用到一定門檻值,預設是5秒内20次調用失敗就會啟動熔斷機制。下面我們畫個圖來進行了解:
微服務之間肯定存在互相調用的關系,如下圖,使用者請求進入服務,調用服務A,服務A調用服務B,服務B調用服務C,服務C調用服務D,最後服務D響應給回使用者,一次請求結束:
此時如果服務B當機了,用不了了,那麼這個調用鍊路就會發生故障,服務A一直等待去調用服務B,因為鍊路到不了服務D,不能響應給回使用者,是以這次請求一直未結束,一直占用系統資源,嚴重的話可能會引起整個系統的故障:
我們服務熔斷的含義就是,當服務B發生故障時,我們将服務A對服務B的調用過程給斷掉,我們一開始就設定一個備選服務,當服務B發生故障時,我們可以去調用備選服務,給回使用者響應,已結束本次請求:
當然,這個備選服務可以有兩種選擇:
- 備選服務的功能和服務B一樣,可以正常執行調用服務C的流程,最後傳回正确的響應資訊。
- 備選服務直接傳回錯誤資訊,提醒使用者本次請求發生錯誤。
熔斷機制的注解是
@HystrixCommand
。
我們下面的例子以方式二來說明。
三、執行個體
1、拷貝一份 springcloud-provider-dept-8001 命名為
springcloud-provider-dept-hystrix-8001
。
2、添加 Hystrix的依賴:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
<version>1.4.7.RELEASE</version>
</dependency>
3、在可能發生錯誤的服務上添加一個注解
@HystrixCommand(fallbackMethod = "備選服務名(或函數名)")
。
4、編寫備選服務,Controller 代碼如下:
/提供Restful 服務
@RestController
@RequestMapping("/dept")
public class DeptController {
@Autowired
private DeptService deptService;
@GetMapping("/queryDeptById/{id}")
// 如果這個方法調用失敗,就會執行熔斷備選方法queryDeptByIdHystrix
@HystrixCommand(fallbackMethod = "queryDeptByIdHystrix")
public Dept queryDeptById(@PathVariable("id") Long id){
Dept dept = deptService.queryDeptById(id);
if(dept == null){
throw new RuntimeException("id=>" + id + "不存在該使用者,或者資訊無法找到!");
}
return dept;
}
// 熔斷版的備選方案
public Dept queryDeptByIdHystrix(@PathVariable("id") Long id){
return new Dept()
.setDeptno(id)
.setDname("id=>" + id + "沒有對應的資訊,[email protected]!")
.setDbSource("no this database in Mysql");
}
}
5、在主啟動類上開啟服務熔斷,添加一個注解即可:
接下來開啟服務以及叢集,就可以看到效果了!當服務發生錯誤時,會去執行備選服務,傳回錯誤資訊給使用者!