服務雪崩效應
當一個請求依賴多個服務的時候,正常情況下的訪問如下圖所示:
但是當請求的服務中出現無法訪問、異常、超時等問題時(圖中的I),那麼用戶的請求將會被阻塞:
如果多個用戶的請求中都存在無法訪問的服務,那麼他們都將陷入阻塞的狀態中:
Hystrix的引入,可以通過服務熔斷和服務降級來解決這個問題
Hystrix服務熔斷與服務降級
熔斷機制是應對雪崩效應的一種微服務鏈路保護機制。即當某個服務不可用或者響應時間超時時,會進行服務降級,進而熔斷該節點的服務調用,並快速返回自定義的錯誤以及頁面信息
寫個項目來測試下:參考microservice-student-provider-hystrix-1001模塊新建一個帶服務熔斷的服務提供者模塊(microservice-student-provider-hystrix-1004),把配置和代碼都複製一份到這個項目裏,然後進行修改
1、在pom.xml里加入Hystrix的依賴:
<!--Hystrix相關依賴-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency>
2、在application.yml裏修改下端口和實例名稱:
server:
port: 1004
context-path: /
spring:
application:
name: microservice-student
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/demosite1?useUnicode=true&characterEncoding=utf8
username: root
password: root
jpa:
hibernate:
ddl-auto: update
show-sql: true
eureka:
instance:
#eureka客戶端主機實例名稱
hostname: localhost
#客戶端服務名
appname: microservice-student
#客戶端實例名稱
instance-id: microservice-student:1004
#顯示IP
prefer-ip-address: true
client:
service-url:
#把服務註冊到eureka註冊中心
defaultZone: http://eureka2001.test.com:2001/eureka/,http://eureka2002.test.com:2002/eureka/,http://eureka2003.test.com:2003/eureka/
info:
groupId: com.ue.microservice
artifactId: microservice-student-provider-1004
version: 1.0-SNAPSHOT
負責人: Tom
聯繫電話: 123456
3、在啓動類MicroserviceStudentProviderHystrix1004Application.java加入@EnableCircuitBreaker註解:
4、在服務提供者1004項目中的controller新增測試接口:
@Value("${server.port}")
private String port;
/**
* 測試Hystrix服務降級
* @return
* @throws InterruptedException
*/
@GetMapping(value="/hystrix")
@HystrixCommand(fallbackMethod="hystrixFallback")
public Map<String,Object> hystrix() throws InterruptedException{
Thread.sleep(4000);
Map<String,Object> map=new HashMap<String,Object>();
map.put("code", 200);
map.put("info","工號【" + port + "】正在爲您服務");
return map;
}
public Map<String,Object> hystrixFallback() throws InterruptedException{
Map<String,Object> map=new HashMap<String,Object>();
map.put("code", 500);
map.put("info", "系統【" + port + "】繁忙,稍後重試");
return map;
}
上述接口如果能正常訪問,那返回的是200跟業務數據,但是這裏用了Thread.sleep(2000)來模擬超時,在接口上面加上@HystrixCommand註解以及fallbackMethod,表明這個方法在沒有異常以及沒有超時(hystrix默認1秒算超時)的情況下,才返回正常的業務數據;否則,會進入fallback指定的本地方法,這裏搞的是返回500跟系統繁忙,稍後重試,可以有效的解決雪崩效應以及返回給用戶界面很好的報錯提示信息
5、在服務消費者80項目中的controller新增測試接口:
/**
* 測試Hystrix服務降級
* @return
*/
@GetMapping(value="/hystrix")
@ResponseBody
public Map<String,Object> hystrix(){
return restTemplate.getForObject(PRE_HOST + "/student/hystrix", Map.class);
}
6、開始測試,先啓動三個eureka,再啓動帶hystrix的provider,最後啓動普通的consumer:
然後在瀏覽器地址欄輸入http://localhost/student/hystrix,結果如下:
因爲Hystrix默認1秒就算超時,但線程sleep了2秒,所以會進入到自定義的fallback方法,防止服務雪崩
這裏再將sleep修改成100毫秒進行測試,結果如下:
可以看到返回了正常的業務數據
Hystrix默認超時時間設置
Hystrix默認超時時間是1秒,可以通過Hystrix源碼找到,找到hystrix-core.jar的com.netflix.hystrix包下的HystrixCommandProperties類,類裏有一個default_executionTimeoutInMilliseconds屬性,這個就是默認的超時時間:
系統裏假如要自定義設置Hystrix的默認時間的話,可在application.yml配置文件里加上:
#將Hystrix的默認超時時間設置爲3秒
hystrix:
command:
default:
execution:
isolation:
thread:
timeoutInMilliseconds: 3000
然後在代碼裏將sleep修改成2秒進行測試,結果如下:
再將sleep修改成4秒進行測試,結果如下: