SpringCloud之Hystrix

簡介

在分布式環(huán)境中部逮,許多服務依賴關系中的一些必然會失敗。Hystrix是一個庫,它通過添加延遲容忍和容錯邏輯來幫助您控制這些分布式服務之間的交互藏澳。Hystrix通過隔離服務之間的訪問點、停止跨服務的級聯(lián)故障并提供回退選項來實現(xiàn)這一點耀找,所有這些選項都提高了系統(tǒng)的總體彈性翔悠。

目標

Hystrix的設計目的如下:

  • 為通過第三方客戶端庫訪問的依賴項(通常通過網(wǎng)絡)提供保護和控制延遲和故障。
  • 停止復雜分布式系統(tǒng)中的級聯(lián)故障野芒。
  • 故障快速恢復蓄愁。
  • 在可能的情況下,后退并優(yōu)雅地降級狞悲。
  • 啟用近實時監(jiān)視撮抓、警報和操作控制。

背景

為了解決什么問題摇锋?

復雜分布式體系結構中的應用程序有幾十個依賴項丹拯,每個依賴項在某個時候都不可避免地會失敗。如果主機應用程序沒有從這些外部故障中隔離出來荸恕,那么它就有可能與這些外部故障一起宕機乖酬。

例如,對于一個依賴于30個服務的應用程序融求,其中每個服務都有99.99%的正常運行時間咬像,您可以這樣期望:

99.9930 = 99.7% uptime
0.3% of 1 billion requests = 3,000,000 failures
2+ hours downtime/month even if all dependencies have excellent uptime.

現(xiàn)實通常更糟。
即使當所有依賴項都運行良好時双肤,即使0.01%的停機時間對幾十個服務中的每個服務的總體影響也相當于一個月潛在的停機時間(如果您不為恢復而設計整個系統(tǒng))施掏。

如下面的圖演變:

當一切正常時,請求流可以是這樣的:


當許多后端系統(tǒng)之一成為潛在茅糜,它可以阻止整個用戶請求:


對于高流量七芭,一個后端依賴項成為潛在,可能會導致所有服務器上的所有資源在幾秒鐘內(nèi)飽和蔑赘。
應用程序中通過網(wǎng)絡或客戶機庫到達可能導致網(wǎng)絡請求的每個點都是潛在故障的來源狸驳。比故障更糟的是,這些應用程序還可能導致服務之間的延遲增加缩赛,從而備份隊列耙箍、線程和其他系統(tǒng)資源,從而導致系統(tǒng)中出現(xiàn)更多級聯(lián)故障酥馍。


工作原理

工作流程圖:

工作流程圖

1. 構造一個HystrixCommand或HystrixObservableCommand對象

第一步是構造一個HystrixCommand或HystrixObservableCommand對象來表示對依賴項的請求辩昆。將請求發(fā)出時需要的任何參數(shù)傳遞給構造函數(shù)。
如果期望依賴項返回單個響應旨袒,則構造一個HystrixCommand對象汁针。例如:

HystrixCommand command = new HystrixCommand(arg1, arg2);

如果期望依賴項返回發(fā)出響應的可觀察對象术辐,則構造一個HystrixObservableCommand對象。例如:

HystrixObservableCommand command = new HystrixObservableCommand(arg1, arg2);
2.執(zhí)行命令

有四種方法可以執(zhí)行命令施无,使用以下四種方法之一的Hystrix命令對象(前兩種方法只適用于簡單的HystrixCommand對象辉词,不適用于HystrixObservableCommand):

  • execute() — blocks, then returns the single response received from the dependency (or throws an exception in case of an error)
  • queue() — returns a Future with which you can obtain the single response from the dependency
  • observe() — subscribes to the Observable that represents the response(s) from the dependency and returns an Observable that replicates that source Observable
  • toObservable() — returns an Observable that, when you subscribe to it, will execute the Hystrix command and emit its responses
3.是否緩存了響應

如果為該命令啟用了請求緩存,并且在緩存中可用對請求的響應猾骡,則此緩存的響應將立即以可觀察到的形式返回瑞躺。

4. 電路打開了嗎?

當您執(zhí)行該命令時,Hystrix將與斷路器一起檢查電路是否打開兴想。
如果電路打開(或“跳閘”)幢哨,那么Hystrix將不執(zhí)行命令,而是將流路由到(8)獲取回退嫂便。
如果電路被關閉嘱么,則流繼續(xù)到(5),檢查是否有可用的容量來運行命令顽悼。

5.線程池/隊列/信號量是否已滿?

如果與該命令關聯(lián)的線程池和隊列(或信號量,如果不在線程中運行)已滿几迄,那么Hystrix將不執(zhí)行該命令蔚龙,而是立即將流路由到(8)獲取回退。

6.HystrixObservableCommand.construct()或HystrixCommand.run ()

這里映胁,Hystrix通過為此目的編寫的方法調(diào)用對依賴項的請求木羹,方法如下:

如果run()或construct()方法超過了命令的超時值,線程將拋出一個TimeoutException(如果命令本身不在自己的線程中運行解孙,則單獨的計時器線程將拋出一個TimeoutException)坑填。在這種情況下,Hystrix將響應路由到8弛姜。獲取回退脐瑰,如果最終返回值run()或construct()方法沒有取消/中斷,那么它將丟棄該方法廷臼。
請注意苍在,沒有辦法強制潛在線程停止工作——Hystrix在JVM上能做的最好的事情就是拋出InterruptedException。如果由Hystrix包裝的工作不尊重interruptedexception荠商,那么Hystrix線程池中的線程將繼續(xù)它的工作寂恬,盡管客戶機已經(jīng)收到了TimeoutException。這種行為可能會使Hystrix線程池飽和莱没,盡管負載“正確釋放”初肉。大多數(shù)Java HTTP客戶端庫不解釋interruptedexception。因此饰躲,請確保正確配置HTTP客戶機上的連接和讀/寫超時牙咏。
如果該命令沒有拋出任何異常并返回一個響應臼隔,那么Hystrix將在執(zhí)行一些日志記錄和度量報告之后返回此響應。在run()的情況下眠寿,Hystrix返回一個可觀察的對象躬翁,該對象發(fā)出單個響應,然后發(fā)出一個onCompleted通知;在construct()的情況下盯拱,Hystrix返回由construct()返回的相同的可觀察值盒发。

7.計算電路健康

Hystrix向斷路器報告成功、失敗狡逢、拒絕和超時宁舰,斷路器維護一組滾動計數(shù)器,用于計算統(tǒng)計數(shù)據(jù)奢浑。
它使用這些統(tǒng)計數(shù)據(jù)來確定電路應該在什么時候“跳閘”蛮艰,在這一點上,它會短路任何后續(xù)的請求雀彼,直到恢復期結束壤蚜,在此期間,它會在第一次檢查某些健康檢查之后再次關閉電路徊哑。

8.回退

Hystrix試圖恢復你的回滾命令執(zhí)行失敗時:當一個異常的構造()或()運行(6),當命令電路短路,因為打開(4),當命令的線程池和隊列或信號能力(5),或者當命令已超過其超時長度袜刷。
詳情參考官網(wǎng):https://github.com/Netflix/Hystrix/wiki/How-it-Works#8-get-the-fallback

9. 返回成功的響應

如果Hystrix命令成功,它將以可觀察到的形式返回響應或響應給調(diào)用者莺丑。根據(jù)您如何調(diào)用上面步驟2中的命令著蟹,這個可觀察對象可能在返回給您之前進行轉換:

  • execute() — 以與.queue()相同的方式獲取一個Future,然后在這個Future上調(diào)用get()來獲取可觀察對象發(fā)出的單個值.
  • queue() — 將可觀察對象轉換為BlockingObservable梢莽,以便將其轉換為未來萧豆,然后返回此未來
  • observe() — 立即訂閱可觀察對象,并開始執(zhí)行命令的流;返回一個可觀察對象昏名,當您訂閱該對象時涮雷,將重播排放和通知
  • toObservable() — 返回可觀察值不變;您必須訂閱它,才能真正開始執(zhí)行命令的流程

更多原理可以移步官網(wǎng)
https://github.com/Netflix/Hystrix/wiki/How-it-Works

使用

加入依賴

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

在ribbon中使用

使用@EnableHystrix開啟

@SpringBootApplication
@EnableEurekaClient
@EnableDiscoveryClient
@EnableHystrix
public class CloudServiceRibbonApplication {

    public static void main(String[] args) {
        SpringApplication.run(CloudServiceRibbonApplication.class, args);
    }


    @Bean
    @LoadBalanced
    RestTemplate restTemplate() {
        return new RestTemplate();
    }

}

該注解對該方法創(chuàng)建了熔斷器的功能轻局,并指定了fallbackMethod熔斷方法份殿,熔斷方法直接返回了一個字符串,字符串為"hi,"+name+",sorry,error!"


@Service
public class TestService {


    @Autowired
    RestTemplate restTemplate;

    @HystrixCommand(fallbackMethod = "hiError")
    public String hiService(String name) {
        return restTemplate.getForObject("http://CLOUD-EUREKA-CLIENT/hi?name="+name,String.class);
    }

    public String hiError(String name) {
        return "hi,"+name+",sorry,error!";
    }

}
在Feign中使用

feign.hystrix.enabled: true 開啟hystrix

eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:8761/eureka/
server:
  port: 8765
spring:
  application:
    name: cloud-service-feign

feign.hystrix.enabled: true

@EnableFeignClients啟動

@SpringBootApplication
@EnableEurekaClient
@EnableDiscoveryClient
@EnableFeignClients
public class CloudServiceFeginApplication {

    public static void main(String[] args) {
        SpringApplication.run(CloudServiceFeginApplication.class, args);
    }

}

fallback:配置連接失敗等錯誤的返回類

@FeignClient(value = "cloud-eureka-client",fallback = TestServiceHystric.class)
public interface TestService {

    @RequestMapping(value = "/hi",method = RequestMethod.GET)
    String sayHiFromClientOne(@RequestParam(value = "name") String name);

}

當訪問接口有問題時嗽交,直接調(diào)用此接口返回卿嘲。

@Component
public class TestServiceHystric implements  TestService{
    @Override
    public String sayHiFromClientOne(String name) {
        return "sorry "+name;
    }
}

更多使用技巧可參考官網(wǎng):
https://github.com/Netflix/Hystrix/wiki/How-To-Use

總結

在微服務架構中通常會有多個服務層調(diào)用,基礎服務的故障可能會導致級聯(lián)故障夫壁,進而造成整個系統(tǒng)不可用的情況拾枣,這種現(xiàn)象被稱為服務雪崩效應。服務雪崩效應是一種因“服務提供者”的不可用導致“服務消費者”的不可用,并將不可用逐漸放大的過程。

熔斷器的原理很簡單梅肤,如同電力過載保護器司蔬。它可以實現(xiàn)快速失敗,如果它在一段時間內(nèi)偵測到許多類似的錯誤姨蝴,會強迫其以后的多個調(diào)用快速失敗俊啼,不再訪問遠程服務器,從而防止應用程序不斷地嘗試執(zhí)行可能會失敗的操作左医,使得應用程序繼續(xù)執(zhí)行而不用等待修正錯誤授帕,或者浪費CPU時間去等到長時間的超時產(chǎn)生。熔斷器也可以使應用程序能夠診斷錯誤是否已經(jīng)修正浮梢,如果已經(jīng)修正跛十,應用程序會再次嘗試調(diào)用操作。

更多優(yōu)質文章:

最后

如果對 Java秕硝、大數(shù)據(jù)感興趣請長按二維碼關注一波芥映,我會努力帶給你們價值。覺得對你哪怕有一丁點幫助的請幫忙點個贊或者轉發(fā)哦远豺。

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末奈偏,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子躯护,更是在濱河造成了極大的恐慌霎苗,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,907評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件榛做,死亡現(xiàn)場離奇詭異,居然都是意外死亡内狸,警方通過查閱死者的電腦和手機检眯,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,987評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來昆淡,“玉大人锰瘸,你說我怎么就攤上這事“毫椋” “怎么了避凝?”我有些...
    開封第一講書人閱讀 164,298評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長眨补。 經(jīng)常有香客問我管削,道長,這世上最難降的妖魔是什么撑螺? 我笑而不...
    開封第一講書人閱讀 58,586評論 1 293
  • 正文 為了忘掉前任含思,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘含潘。我一直安慰自己饲做,他們只是感情好,可當我...
    茶點故事閱讀 67,633評論 6 392
  • 文/花漫 我一把揭開白布遏弱。 她就那樣靜靜地躺著盆均,像睡著了一般。 火紅的嫁衣襯著肌膚如雪漱逸。 梳的紋絲不亂的頭發(fā)上泪姨,一...
    開封第一講書人閱讀 51,488評論 1 302
  • 那天,我揣著相機與錄音虹脯,去河邊找鬼驴娃。 笑死,一個胖子當著我的面吹牛循集,可吹牛的內(nèi)容都是我干的唇敞。 我是一名探鬼主播,決...
    沈念sama閱讀 40,275評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼咒彤,長吁一口氣:“原來是場噩夢啊……” “哼疆柔!你這毒婦竟也來了?” 一聲冷哼從身側響起镶柱,我...
    開封第一講書人閱讀 39,176評論 0 276
  • 序言:老撾萬榮一對情侶失蹤旷档,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后歇拆,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體笆焰,經(jīng)...
    沈念sama閱讀 45,619評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡藤肢,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,819評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片能犯。...
    茶點故事閱讀 39,932評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡值漫,死狀恐怖担孔,靈堂內(nèi)的尸體忽然破棺而出色洞,到底是詐尸還是另有隱情,我是刑警寧澤贯溅,帶...
    沈念sama閱讀 35,655評論 5 346
  • 正文 年R本政府宣布拄氯,位于F島的核電站,受9級特大地震影響它浅,放射性物質發(fā)生泄漏译柏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,265評論 3 329
  • 文/蒙蒙 一姐霍、第九天 我趴在偏房一處隱蔽的房頂上張望艇纺。 院中可真熱鬧,春花似錦、人聲如沸黔衡。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,871評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽盟劫。三九已至夜牡,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間侣签,已是汗流浹背塘装。 一陣腳步聲響...
    開封第一講書人閱讀 32,994評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留影所,地道東北人蹦肴。 一個月前我還...
    沈念sama閱讀 48,095評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像猴娩,于是被迫代替她去往敵國和親阴幌。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,884評論 2 354

推薦閱讀更多精彩內(nèi)容

  • 你說 以夢為馬 須拼搏向上 你說 前路漫漫 抱歉無法同行 你說 江湖險惡 當心為上策 你說 此去經(jīng)年 愿君前程似錦...
    慕青檸閱讀 460評論 2 2
  • 博客地址:http://davidleee.com原文鏈接:http://davidleee.com/2016/0...
    davidleee閱讀 3,104評論 0 2
  • . 中信萬事達鈦金卡 . 中信siliture 線下3折 . 中國民生vesa 卡 . 浦發(fā)萬事達信用卡 百分之一折
    享悅moonlight閱讀 378評論 0 0
  • 反思自己多少年未提筆寫過文章,當初溫暖的文字早已演變成了稀松平常蟆豫,當初的情懷也變得人間煙火议忽。而現(xiàn)今提筆,卻因為朋友...
    乙宴閱讀 300評論 0 1