熔斷器Hystrix
學習筆記(2020.3.18)
熔斷器的功能:服務保護功能。它也是基於Netflix
的開源框架 Hystrix
實現的,該框架目標在於通過控制那些訪問遠程系統、服務和第三方庫的節點,從而對延遲和故障提供更強大的容錯能力。Hystrix
具備了服務降級、服務熔斷、線程隔離、請求緩存、請求合併以及服務監控等強大功能。
Hystrix
能使你的系統在出現依賴服務失效的時候,通過隔離系統所依賴的服務,防止服務級聯失敗,同時提供失敗回退機制,更優雅地應對失效,並使你的系統能更快地從異常中恢復
使用spring-cloud-starter-hystrix
實現服務降級
1. 引入依賴:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency>
2. 在應用啓動類中使用@EnableCircuitBreaker
或@EnableHystrix
註解開啓Hystrix
的使用:
@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients
@EnableCircuitBreaker
public class ClientApplication {
public static void main(String[] args) {
SpringApplication.run(ClientApplication.class, args);
}
}
3.在服務消費方使用@HystrixCommand
註解來指定服務降級方法
@RestController
public class TestController {
@Autowired
private TestService testService;
/**
* 使用@HystrixCommand註解指定調用不通後降級方法
*
* @return java.util.Map<java.lang.String,java.lang.Object>
* @author: zhihao
* @date: 2019/11/29
*/
@HystrixCommand(fallbackMethod = "fallback")
@GetMapping("/getss")
public Map<String, Object> getss(String id){
Map<String, Object> oneMap = testService.findOneMap("1");
return oneMap;
}
public Map<String, Object> fallback(String id) {
System.out.println("熔斷器啓動");
HashMap<String, Object> hashMap = new HashMap<>();
hashMap.put("error","熔斷器啓動後快速返回結果給客戶端的內容"+id);
return hashMap;
}
}
注意事項:
-
@HystrixCommand
:此註解表示此方法是hystrix
方法,其中fallbackMethod
定義回退方法的名稱 -
Map<String, Object> fallback(String id)
:HystrixCommand
的回退方法,此方法必須和hystrix
的執行方法在相同類中。可以把HystrixCommand
的執行參數和執行失敗的異常傳入回退方法中
使用Feign 本身支持Hystrix
,不需要額外引入依賴!
1. 在application.yml
配置文件上加上以下內容,開啓Hystrix
#啓用feign的hystrix(熔斷器)
feign:
hystrix:
enabled: true
2. 在模塊包下創建Hystriximpl
包,包下創建熔斷實現類,實現自己消費方接口
//自己消費方的接口
@FeignClient(name = "EUREKA-TEST")
public interface TestService {
@RequestMapping(value = "/findOneMap",method = RequestMethod.GET)
Map<String, Object> findOneMap(@RequestParam("id") String id);
}
//熔斷實現類
@Component //記得交給框架管理bean
public class LabelClientimpl implements TestService {
@Override
public Map<String, Object> findOneMap(String id) {
System.out.println("熔斷器啓動");
Map<String, Object> map = new HashMap<>();
map.put("error","熔斷器啓動"+id);
return map;
}
}
3. 修改TestService
的註解:
@FeignClient(name = "EUREKA-TEST",fallback = LabelClientimpl.class) //指定降級實現類
public interface TestService {
啓動服務測試遠程服務調用不通,是否走了熔斷器實現類,到此結束!
如果需要知道導致熔斷效果的回退,需實現FallbackFactory
FallbackFactory
是feign.hystrix
提供的回退工廠! (具體實現)
/**
* @Author: zhihao
* @Date: 2020/3/18 17:40
* @Description: 可以知道原因的回退工廠
* @Versions 1.0
**/
@Component
public class MyFallbackFactory implements FallbackFactory<TestService> {
@Override
public TestService create(Throwable cause) {
return new TestService() {
@Override
public Map<String, Object> findOneMap(String username) {
Map<String, Object> resultMap = new LinkedHashMap<>();
resultMap.put("status",500);
resultMap.put("message",cause.getMessage());
return resultMap;
}
};
}
}
然後接口修改爲:
@FeignClient(name = “EUREKA-TEST”,fallbackFactory = MyFallbackFactory.class)
進行測試!
Hystrix
的線程隔離策略:
# 線程隔離設置
hystrix:
command:
default:
execution:
isolation:
strategy: SEMAPHORE
作用在線程中執行的命令具有額外的保護層,可防止超出網絡超時所能提供的延遲。
THREAD
—它在單獨的線程上執行,併發請求受線程池中線程數的限制SEMAPHORE
—它在調用線程上執行,併發請求受信號量限制通常,只有
HystrixCommand
在調用量很大(每個實例每秒數百個)以至於各個線程的開銷過高時,才應爲熔斷器使用信號隔離。這通常僅適用於非網絡呼叫。
擴展資料:
熔斷器超時配置:
hystrix:
command:
default: #default全局有效,service id指定應用有效
execution:
timeout:
enabled: true
isolation:
thread:
#斷路器超時時間,默認1000ms,斷路器的超時時間需要大於ribbon的超時時間,不然不會觸發重試
timeoutInMilliseconds: 5000
ribbon:
ConnectTimeout: 3000 #ribbon請求連接的超時時間,默認值2000
ReadTimeout: 3000 #負載均衡超時時間,默認值5000
OkToRetryOnAllOperations: true #對所有操作請求都進行重試,默認false
MaxAutoRetries: 0 #對當前實例的重試次數,默認0
MaxAutoRetriesNextServer: 1 #對切換實例的重試次數,默認1
注意事項:
- 如果
hystrix.command.default.execution.timeout.enabled
爲true,則會有兩個執行方法超時的配置,一個就是ribbon
的ReadTimeout
,一個就是熔斷器hystrix
的timeoutInMilliseconds
, 此時誰的值小誰先生效, Hystrix超時單獨配置不行,還要額外設置 Ribbon 的超時時間 - 如果
hystrix.command.default.execution.timeout.enabled
爲false,則熔斷器不進行超時熔斷,而是根據ribbon的ReadTimeout
拋出的異常而熔斷,也就是取決於ribbon
- 由於ribbon的重試機制,通常熔斷的超時時間需要配置的比
ReadTimeout
長,ReadTimeout
比ConnectTimeout
長,否則還未重試,就熔斷了!