什么是熔斷?
熔斷簡單來說就是在單個服務出現(xiàn)問題,不可用時,為了避免引發(fā)更嚴重的問題,導致整個服務鏈路不可用的情況下,可以采用熔斷的方式來避免。熔斷一般情況下意味著服務的降級,可以理解為是一種異常兜底策略,需要服務的上游調用方來實現(xiàn)。
在訪問量比較高的情況下,客戶端訪問A節(jié)點,A節(jié)點一個依賴的服務節(jié)點B出現(xiàn)延遲(或者不可用),這種情況下,無論是重試策略(重試3次)也好,或者超時策略(超過1S返回失敗或者默認結果)也好,都會比正常請求消耗更多的資源,這時在流量高的場景有可能造成A服務資源被沾滿,從而導致A服務其他接口也出現(xiàn)延遲或者不可用情況,再嚴重一些可能會出現(xiàn)雪崩,A服務依賴的上游也不可用,進而整個集群鏈路崩潰。
因此,服務異常時可以通過熔斷的方式來進行快速的失敗,避免后續(xù)流量繼續(xù)請求到服務B,避免雪崩。
熔斷更多的是指服務之間的熔斷,熔斷通常都會有恢復策略。
什么是降級?
降級,其實也是一種兜底策略,可以理解為主方案行不通了,換一個備用方案。比如,查詢緩存失敗,改為查詢數(shù)據(jù)庫,查詢數(shù)據(jù)庫也失敗,返回“系統(tǒng)繁忙”給到用戶,這種就是降級。再比如,A服務調用B服務,調用失敗,返回“系統(tǒng)繁忙”也算降級,如果此時進行重試,那么可以叫“容錯”。
降級其實有很多方案:
- 被動降級:服務不可用時,返回備用數(shù)據(jù),或者提示文案。比如,廣告推送,正常推送查詢用戶感興趣的,如果服務不可用,改為推送默認廣告。
- 主動降級:人為的把服務設置為不可用。比如雙十一,將評論,收藏等功能主動降級為不可用,避免用戶請求占用服務資源。一般通過預制的降級開關實現(xiàn)。收到客戶端請求后,不會真的去請求評論,收藏服務,直接返回用戶,功能不可用。
- 自動降級:通過預制的規(guī)則,自動的實現(xiàn)降級,自動實現(xiàn)恢復。比如,熔斷導致的降級,限流觸發(fā)降級,超時降級等。
自動降級與被動降級區(qū)別主要是:是否可以自動恢復。
被動降級強調的是,不受控制??梢岳斫鉃楹唵蔚膇f、else每次請求過來都會進行判斷。
自動降級強調的是,自動化??梢岳斫夥粘霈F(xiàn)問題,達到閾值條件時拒絕后續(xù)請求,同時感知服務狀態(tài),達到可用條件時,再允許后續(xù)請求。
總結
其實無論是熔斷也好,降級也好。主要都是因為,由于服務之間存在依賴性,故障會傳播造成連鎖反應,導致雪崩。為了避免雪崩從而提出了熔斷和降級的概念。
區(qū)別
熔斷更注重的是服務之間請求的問題,強調服務之間的請求可以實現(xiàn)自我恢復。面對的是服務異常問題。
降級更注重功能的主次問題,在資源有限的情況下優(yōu)先保證核心功能可用,次要功能做降級處理。面對的是服務資源。
可以理解為,熔斷是降級的一種,屬于自動降級。(降級也是限流的一種方式)
Hystrix
簡介
Hystrix簡單來說就是:對某個服務的調用在一定的時間內(默認10s,由 metrics.rollingStats.timeInMilliseconds配置),有超過一定次數(shù)(默認20次,由 circuitBreaker.requestVolumeThreshold參數(shù)配置)并且失敗率超過一定值(默認 50%,由circuitBreaker.errorThresholdPercentage配置),該服務的斷路器會打開。 返回一個由開發(fā)者設定的fallback。
作用
主要是通過快速失敗,快速恢復,對服務依賴節(jié)點不可用故障進行保護,避免級聯(lián)故障。能夠快速的回退,實現(xiàn)服務降級。并且支持實時監(jiān)控、告警和操作控制。
設計原則
- 使用快速失敗代替請求排隊,減少負載。
- 防止任何單個依賴故障耗盡容器所有線程資源。使用隔離的方式,減少故障帶來的影響。
- 根據(jù)實際情況提供降級方法,保護用戶不受影響。
- 通過實時的監(jiān)控增強故障的感知。
Hystrix 如何實現(xiàn)熔斷
場景
服務調用者A,需要調用服務提供者B的接口??紤]到B服務如果出現(xiàn)超時不可用情況,要減輕對A服務的影響。比如:B服務接口響應時間超過1S,開啟降級,提供 fall back方法(服務調用者自行根據(jù)業(yè)務創(chuàng)建該方法),返回默認信息(也可以默認失?。贐服務接口出現(xiàn)不穩(wěn)定(10秒內調用20次失敗率50%以上時,開啟熔斷,后續(xù)5秒的請求直接走降級fall back 方法 返回默認信息)
熔斷的默認觸發(fā)機制
使用Histrix 默認策略 10秒內 調用20次 失敗率50%以上 觸發(fā)熔斷 默認熔斷 5s
步驟
服務提供者
- 提供服務接口。
- 模擬超時失敗。
- 啟動服務
服務調用者
- 引入jar包。
- 開啟熔斷配置注解。
- 啟動配Enable注解。@EnableCircuitBreaker
- 如果使用Fein 對Fein 需要開啟Histrix 支持(yml 配置文件增加 feign.hystrix.enabled=true)
- 在調用服務提供者接口處進行配置。使用注解方式。
- @HystrixCommand
- 也可以使用默認的配置屬性
- 創(chuàng)建與注解配置一致的fall back方法
- fall back 是作為一個降級的方法,我們也可以不使用降級。
思考
如何定義失敗
針對上述場景,模擬超時即為失敗。那么對于線上的正常運行情況,如何定義失???比如拋出了異常(正常響應時間內),又比如服務鏈接找不到。
回想一下熔斷的目的,主要是為了保證服務提供方A不可用時,調用者B仍然耗費B自身的資源去請求不可用的服務A,此時B調用A耗費的資源如果比正常調用要多那么需要考慮熔斷,避免B自身資源消耗完畢,引發(fā)雪崩。如果B調用A耗費的資源較少,那么熔斷還有必要么?但是不做限制 似乎又有點傻,明知道不行還非要去嘗試。而且如果出現(xiàn)異常情況,通常都是需要去記錄堆棧,發(fā)送告警。
所以最終認為,失敗可大概分為三種,超時、異常、服務不可用,都有必要做熔斷。
如何確定生效的范圍,有些接口配置,有些不需要配置。不同接口可以單獨使用配置,也可以默認配置
對于服務A來說可能會調用N個不同的服務,那么對于不同的服務類型,可能會采取不同的降級措施,比如A調用B的情況比較少,那么可以將請求的次數(shù)適當調低一些,避免因設置過高,不滿足熔斷條件導致熔斷不生效。
此外對于不同的服務提供者,還可以基于不同的情況,做服務隔離。常用的隔離方式有兩種,1種是線程池的隔離,一種是信號量的隔離。其根本就是對不同的服務做不同的資源限制。避免一個服務不可用導致其他服務資源也被消耗完發(fā)生雪崩情況。
假如有三個服務A/B/C
線程池隔離是指,對服務A/B/C分配不同的線程池,A服務出現(xiàn)異常導致線程沾滿,不會影響B(tài)/C服務的線程池,B/C服務扔可以正常的工作。
信號量隔離是指,使用同一個線程池,但是對不同的服務設置不同的信號量。比如線程池共有10個線程,A/B/C服務的信號量分別為2、3、5。每次請求都需要驗證其對應的信號量是否有剩余。
Histrix 開啟熔斷后,如果沒有對依賴的服務開啟fall back 那么會如何?
如果沒有配置fall back 會使用默認的方式。
Histrix 開啟后 是針對所有的服務 還是針對特定的服務開啟
開啟時針對所有的服務??梢允褂媚J配置,
Histrix 優(yōu)缺點,是否一定要開啟?
個人認為,在分布式微服務環(huán)境中,一些流量較高的核心業(yè)務系統(tǒng)需要開啟熔斷,因為一個系統(tǒng)對外提供的肯定不止一種服務,如果不開啟熔斷,很容易導致某一種服務因為鏈路的某個依賴環(huán)節(jié)出現(xiàn)故障導致整個系統(tǒng)服務資源受影響。
如果服務流量較小,且非核心也并不是很重要,那么可以采用一種通用的配置,或者不用也可。因為配置也會有額外的成本,需要考慮合適的參數(shù),服務隔離,fall back 而且很有可能配置了也沒有什么太大的效果。
比如服務 QPS 10 以下, 開啟 熔斷 5秒其實并沒有多大的價值。
Hystrix 原理
Hystrix主要是通過攔截器的方式,嵌入Feign的請求過程中。
- 在獲取到請求后,會先驗證是否已開啟熔斷開關,如果沒有則放行,有則直接返回降級。
- 如果沒有開啟熔斷開發(fā),判斷10s內是否已大于設置的閾值上線(20次),沒有直接放行,有則需要獲取失敗占比
- 如果失敗占比達到閾值(50%),直接開啟熔斷開關。同時記錄開關開啟時間,方便后續(xù)自動恢復。如果低于閾值,放行。