SpringCloud Hystrix 容錯保護

 

容錯

 在一個分佈式系統裏,一個服務每每要調用多個服務,可能存在某個服務調用失敗, 好比超時、異常等,前端

 要使用容錯框架保證在某些服務調用出問題時,不會拖垮整個調用鏈路,系統依然可用。git

 

 

Hystrix

Hystrix是一個容錯框架,提供了隔離、熔斷、服務降級、監控、cache等功能,能夠有效防止被調服務故障形成的級聯故障。github

和eureka、ribbon、feign同樣,hystrix也是Netflix旗下的項目,都被SpringCloud集成了。redis

  

 

服務限流

當此消費者對某提供者請求個數較多時,消費者能夠限制自身對提供者發起的請求個數,請求個數超過指定的值時,使請求快速失敗。spring

Hystrix的限流方式有2種:線程池、信號量。api

 

 

服務監控

監控請求的失敗率(必定時間內,請求失敗個數)達到閾值,就打開斷路器,熔斷鏈路,使後續的請求快速失敗。tomcat

 

 

熔斷

熔斷服務,包含被調用者、鏈路的下游服務,防止下游服務的故障影響到上游服務。springboot

 

 

服務降級

服務調用失敗默認會返回一堆英文的錯誤信息給用戶,很不友好。網絡

服務降級是在服務調用失敗時自動執行預案,預案使用相同參數表、返回值類型,是備胎、次選,併發

預案能夠只保留核心業務、拋棄不重要的業務,好比電商網站qps很大時,用戶查詢商品信息這一操做,標準業務是獲取商品信息+評論+類似商品(商品推薦),預案只保留查詢商品信息這一核心業務,去掉獲取評論、推薦商品等非核心業務。

預案也能夠連核心業務都不要,直接給出「太擠了,請稍後重試」之類的友好提示。

 

 

熔斷和降級的異同點

相同點:從可用性和可靠性觸發,防止系統崩潰,某些功能暫時不可用

不一樣點:服務熔斷通常是下游服務故障致使的,而服務降級通常是從服務負載考慮,由調用方控制

 

 

自我修復

自我修復其實就是斷路器狀態的切換,斷路器打開(熔斷)後5min內的請求都快速失敗;5min後斷路器半開,放行部分請求,

若是這些請求(服務調用)都成功了,說明問題已修復,關閉斷路器,鏈路恢復通行;不然繼續下一個5min。

5min是窗口期,數值能夠調。

 

 

 


 

 

 

使用Hystrix

Hystrix是在消費者(調用方)中使用的,通常要和Feign搭配使用

 

(1)在建立消費者時勾選Spring Cloud Circuit Breaker -> Hystrix [Maintenance]

也能夠手動加hystrix的依賴:

    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
    </dependency>

 

 

(2)引導類上加 @EnableCircuitBreaker或@EnableHystrix

 @EnableHystrix中包含了@EnableCircuitBreaker這個註解

 

 

(3)在controller中設置回退方法

@Controller
@RequestMapping("/api/v1/user")
public class UserController {
    @Resource
    // private RestTemplate restTemplate;
    private OrderFeignService orderFeignService;

    @RequestMapping("order/{user_id}")
    @ResponseBody
    @HystrixCommand(fallbackMethod = "findOrdersByUserIdFail")  //指定回退方法
    public Map<String,Object> findOrdersByUserId(@PathVariable("user_id") Integer userId){
        //調用服務
        // List<Order> orders = restTemplate.getForObject("http://order-service/api/v1/order/list/" + userId, List.class);
        List<Order> orders = orderFeignService.findOrdersByUserId(userId);

        HashMap<String, Object> map = new HashMap<>();
        map.put("code", 0);
        map.put("data", orders);

        return map;
    }


    /**
     * 回退方法,回退方法命名通常是原方法名+Fail
     */
    public Map<String,Object> findOrdersByUserIdFail(Integer userId){
        //參數:遠程服務接口,返回值類型(目標類型)
        HashMap<String, Object> map = new HashMap<>();
        map.put("code", -1);
        map.put("msg", "人太多了,你被擠出來了,請稍後重試");
        return map;
    }
    
}

Hystrix通常是在controller中設置的,也能夠在其它地方進行設置。但服務調用要寫在service層、而後在controller中調用service層,我這裏圖方便直接在controller中調用服務。

使用Feign、RestTemplate調用服務均可以。

 

返回的時候通常用map裝載數據,code表示處理狀況,前端或上游服務根據碼值肯定處理的狀況,進行對應的數據展現。

好比code=xx表示處理成功了,若是是數據查詢,用表格仍是什麼把獲取的數據展現出來;若是code=xx表示處理失敗,用提示框告訴用戶失敗了。

 固然回退方法能夠直接返回null,若是返回null,前端、上游服務處理返回結果時須要先判斷返回的數據是否爲null。

 

 

@HystrixCommand(fallbackMethod = "findOrdersByUserIdFail")標註在某個方法上,只對該方法有效;

@DefaultProperties(defaultFallback = "findOrdersByUserIdFail")標註在類上,對類中全部的方法都有效,該類中的某個方法執行失敗時,都會調用默認的回退方法來代替。

 

 

 


 

 

 

使用Feign自帶的Hystrix

上面的方式使用的是單獨的Hystrix,也可使用Feign內置的Hystrix。

 

一樣是在消費中使用的,建立消費者時不須要勾選Hystrix,不須要添加Hystrix的依賴,由於Feign的依賴中已經包含了Hystrix。

 

在引導類中不須要使用Hystrix的註解

@EnableFeignClients
// @EnableHystrix
// 或者@EnableCircuitBreaker

 

 

(1)在配置文件中開啓feign自帶的hystrix

feign:
  hystrix:
    enabled: true

默認是false,須要手動開啓

 

 

(2)寫一個類實現Feign接口,和Feign接口放在同一個包下

@Component  //放到spring容器中
public class OrderFeignServiceFallback implements OrderFeignService {

    //實現的方法就是接口中對應方法的回退方法
    @Override
    public List<Order> findOrdersByUserId(Integer user_id) {
        return null;
    }

}

 

 

(3)在Feign接口中指定對應的回退類

@FeignClient(name = "order-service", fallback = OrderFeignServiceFallback.class) 
public interface OrderFeignService {

    @GetMapping("/api/v1/order/list") 
    List<Order> findOrdersByUserId(@RequestHeader("user_id") Integer user_id);

}

 

使用時不須要使用 @HystrixCommand 指定回退方法,調用失敗時會自動執行回退類中對應的回退方法。

 

 

 


 

 

 

2種方式的比較

  • 做用範圍

第一種在哪裏使用都行,能夠給controller、service、dao或者其餘地方的方法指定回退方法,哪一個方法均可以加回退方法;

第二種只是給服務調用加回退方法,只做用於服務調用的語句。

 

  • 服務調用方式

第一種可使用RestTemplate或者Feign,第二種只能使用Feign。

 

總之第二種的使用範圍頗有限,只能對Feign方式的服務調用起到容錯保護;

第一種的使用範圍十分普遍,不侷限於服務調用,可對整個應用起到容錯保護,功能更增強大。

 

 

 


 

 

 

報警通知

一、通知用戶

有些服務須要一段時候後纔會處理,好比訂單處理,會先放到消息隊列中,逐個處理,

若是處理失敗(服務調用失敗)須要及時通知用戶,比xx分鐘內到帳、xx分鐘內出票,若是服務調用失敗,在回退方法中要通知用戶。

若是是車票、電影票、充話費之類較爲重要的,要在回退方法中記錄日誌,並調用短信接口及時告知用戶出票失敗、充值失敗,退款預計xx小時內到帳。

 

通知時,若是當前線程還要作一些操做,好比返回數據給上游服務,通知是一個單獨的業務,能夠新建一個線程來通知,不要阻塞當前線程。

 

 

二、通知系統管理員、運維

統計服務調用失敗的次數,若是指定時間內服務調用失敗次數達到指定值,或者指定時間內服務調用失敗的比例達到指定值,就以短信或者email的方式通知運維、管理員。

 

能夠寫一個工具類,用一個靜態變量記錄服務調用總數,調用某服務一次就+1,再使用一個靜態變量統計該服務調用失敗的次數;

寫一個springboot定時任務,好比每5min執行一次,檢測調用總次數、服務調用失敗比例,達到指定值就通知管理員、運維,

檢測調用總次數是爲了確認被調者是否可能出問題了,不能調用總數一、失敗率100%就通知管理員,多是用戶本身的問題。

 

通知以後或者比例未達到指定值,將統計值清空,從新統計下一個5min。

須要作好日誌記錄,方便管理員找出問題。

 

好比說被調用的服務集羣掛了,不能每隔5min就通知管理一次,人家都開始處理了,你還一直通知。

能夠在管理面板中提供按鈕,點擊能夠關閉、開啓通知管理員的功能,管理員收到故障通知後在面板中關閉通知管理員的功能,開始排查問題,解決後再開啓通知管理員的功能。

也能夠通知管理員以前先檢測redis上有沒有某個鍵值對,有就說明通知過了,再也不通知;沒有就設置此鍵值對,並指定過時時間,再通知管理員。好比過時時間設置爲2h,2h通知一次。

 

 

 


 

 

 

Hystrix參數設置

Hystrix的參數配置能夠寫在@HystrixCommand(標註在方法上,只對該方法有效)、@DefaultProperties(標註在類上,對類中全部的方法都有效)註解中,

但配置天然是寫在配置文件中好些,官方也是寫在配置文件中的。

  

 Hystrix的配置是寫在消費者中的,經常使用配置以下:

hystrix:
  command:
    default:
      execution:
        #是否啓用超時,默認true,通常都是設置爲true
        #timeout:
          #enabled: true
        isolation:
          #有2種隔離策略:THREAD 線程池(默認)、SEMAPHORE 信號量
          strategy: THREAD
          thread:
            #超時時間,默認1000,ms
            timeoutInMilliseconds: 4000
          #semaphore:
            #設置信號量最大值,默認10
            #maxConcurrentRequests: 100

上面使用的是hystrix,參數前綴是hystrix ;若是使用feign自帶的hystrix,參數前綴是 feign: hystrix  

 

 

超時時間指的是@HystrixCommand標註的方法執行的時間,若是使用的是Feign自帶的Hystrix,指定的是服務調用的時間。

超時自動返回失敗,若是將超時時間關閉,則一直等待服務調用完成,不會超時。通常都開啓超時時間。

 

 

隔離策略即服務限流,消費者通常都會對提供者發起多個服務調用請求,消費者能夠設置服務限流,限制自己對提供者的併發請求數。有2種策略

(1)THREAD  線程池,也叫作線程隔離,默認的隔離策略

 爲每一個被調用的服務都建立一個線程池,將每一個服務調用請求都包裝爲一個線程,放到線程池中。

線程池中的服務調用請求都是正在執行的,若線程池滿了,放在隊列中排隊等待,若隊列也滿了,則後續對該被調者的請求直接快速失敗。

Hystrix使用的是jdk自帶的線程池,不是tomcat的線程池。併發執行的服務調用數取決於線程池能容納的線程數。

 

 

(2)SEMAPHORE  信號量

信號量便可同時處理的請求個數,默認值10。

調用一次該服務,將信號量-1,一個調用請求結束將信號量+1,信號量爲0時再也不接受對該服務的調用請求,直接快速失敗。

信號量適用於高併發服務調用,好比每秒數千次服務調用,由於使用線程池會致使線程池中同時存在幾千個線程,開銷巨大。

不用將服務調用請求包裝爲單獨的線程,速度更快,但信號量通常只用於非網絡調用。

 

 快速失敗是指不調用服務提供者,直接服務降級,執行回退方法。

 

 

若是要設置Hystrix的更多參數:

github上搜hystrix找到官方 -> WiKi -> 點擊右側的目錄中的Configuration便可查看hystrix所有參數的介紹

直達車    https://github.com/Netflix/Hystrix/wiki/Configuration

相關文章
相關標籤/搜索