<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          SpringCloud下基于Hystrix的服務(wù)實(shí)踐

          共 4419字,需瀏覽 9分鐘

           ·

          2021-11-09 06:47

          Hystrix是Netflix開源的一款分布式容錯(cuò)框架,其為微服務(wù)提供了一整套服務(wù)保護(hù)、容錯(cuò)機(jī)制。從而避免由于個(gè)別服務(wù)故障而引起的級(jí)聯(lián)故障,即所謂的服務(wù)雪崩效應(yīng)

          abstract.jpeg

          服務(wù)降級(jí)

          所謂服務(wù)降級(jí)是指所調(diào)用服務(wù)發(fā)生意外時(shí),調(diào)用自己本地方法(即fallback降級(jí)方法)返回缺省值。而導(dǎo)致服務(wù)降級(jí)的原因包括但不限于服務(wù)超時(shí)、異常、宕機(jī)、熔斷、服務(wù)資源不足(例如線程、信號(hào)量等)等。實(shí)踐過(guò)程中,首先在payment服務(wù)的POM文件引入Hystrix依賴,如下所示

          <dependencyManagement>
          ??<dependencies>

          ????
          ????<dependency>
          ??????<groupId>org.springframework.bootgroupId>
          ??????<artifactId>spring-boot-dependenciesartifactId>
          ??????<version>2.2.2.RELEASEversion>
          ??????<type>pomtype>
          ??????<scope>importscope>
          ????dependency>

          ????
          ????<dependency>
          ??????<groupId>org.springframework.cloudgroupId>
          ??????<artifactId>spring-cloud-dependenciesartifactId>
          ??????<version>Hoxton.SR1version>
          ??????<type>pomtype>
          ??????<scope>importscope>
          ????dependency>

          ??dependencies>
          dependencyManagement>

          <dependencies>
          ??
          ??
          ??<dependency>
          ????<groupId>org.springframework.cloudgroupId>
          ????<artifactId>spring-cloud-starter-netflix-hystrixartifactId>
          ??dependency>

          dependencies>

          可通過(guò)@HystrixCommand注解,配置該方法所對(duì)應(yīng)的降級(jí)方法。具體通過(guò)fallbackMethod屬性配置一個(gè)入?yún)ⅰ⒊鰠㈩愋鸵恢碌慕导?jí)方法。進(jìn)一步地,還可以通過(guò)commandProperties屬性設(shè)置相關(guān)降級(jí)配置。但如果需要對(duì)每個(gè)@HystrixCommand注解都添加重復(fù)的配置,顯然十分麻煩。故可以在類上添加@DefaultProperties注解設(shè)置該類默認(rèn)的降級(jí)屬性配置,其會(huì)對(duì)該類中添加了@HystrixCommand注解的方法,提供默認(rèn)的降級(jí)配置。特別地對(duì)于該類默認(rèn)的降級(jí)方法,一方面通過(guò)defaultFallback屬性設(shè)置;另一方面該降級(jí)方法是無(wú)入?yún)⒌模鰠㈩愋托枰c被降級(jí)的方法保持一致

          @RestController
          @RequestMapping("pay2")
          //?該類默認(rèn)的降級(jí)配置
          @DefaultProperties(defaultFallback?=?"defaultFallback")
          public?class?PaymentController2?{

          ????@GetMapping("/test1")
          ????//?單獨(dú)配置該方法的降級(jí)方法,?并將方法的超時(shí)配置由默認(rèn)1s改為5s
          ????@HystrixCommand(fallbackMethod?=?"timeoutFallback",?commandProperties?=?{
          ????????@HystrixProperty(name?=?"execution.isolation.thread.timeoutInMilliseconds",?value?=?"5000")
          ????})
          ????public?String?test1(@RequestParam?Integer?time)?{
          ????????//?模擬業(yè)務(wù)耗時(shí)
          ????????try?{
          ????????????Thread.sleep(?time?);
          ????????}?catch?(Exception?e)?{
          ????????}

          ????????String?msg?=?"[Payment?Service?-?test1],?time:"?+?time;
          ????????return?msg;
          ????}

          ????@GetMapping("/test2")
          ????//?使用@DefaultProperties注解提供的默認(rèn)降級(jí)相關(guān)配置
          ????@HystrixCommand
          ????public?String?test2(@RequestParam?Integer?time)?{
          ????????//?模擬業(yè)務(wù)耗時(shí)
          ????????try?{
          ????????????Thread.sleep(?time?);
          ????????}?catch?(Exception?e)?{
          ????????}

          ????????String?msg?=?"[Payment?Service?-?test2],?time:"?+?time;
          ????????return?msg;
          ????}

          ????@GetMapping("/test3")
          ????//?使用@DefaultProperties注解提供的默認(rèn)降級(jí)相關(guān)配置
          ????@HystrixCommand
          ????public?String?test3(@RequestParam?Integer?num)?{
          ????????int?result?=?10/num;
          ????????String?msg?=?"[Payment?Service?-?test3],?num:"?+?num;
          ????????return?msg;
          ????}

          ????/**
          ?????*?超時(shí)降級(jí)方法
          ?????*?@param?time
          ?????*?@return
          ?????*/

          ????public?String?timeoutFallback(Integer?time)?{
          ????????return?"payment服務(wù)發(fā)生超時(shí),?param:?time:?"?+?time;
          ????}

          ????/**
          ?????*?默認(rèn)降級(jí)方法
          ?????*?@return
          ?????*/

          ????public?String?defaultFallback()?{
          ????????return?"payment服務(wù)暫不可用";
          ????}

          }

          最后,在啟動(dòng)類上添加@EnableHystrix注解以啟用Hystrix

          @SpringBootApplication
          @EnableDiscoveryClient?//?使用Consul作為注冊(cè)中心時(shí)使用
          @EnableHystrix?//?啟用Hystrix
          public?class?PaymentApplication?{
          ????public?static?void?main(String[]?args)?{
          ????????SpringApplication.run(PaymentApplication.class,?args);
          ????}
          }

          測(cè)試效果如下,符合預(yù)期

          figure 1.jpeg

          服務(wù)熔斷

          Hystrix的服務(wù)熔斷采用斷路器模式的思想進(jìn)行設(shè)計(jì)。在該模式中存在如下三種狀態(tài)

          • Closed:關(guān)閉狀態(tài)。接受請(qǐng)求,服務(wù)的主邏輯可以被訪問調(diào)用
          • Open:打開狀態(tài)。拒絕請(qǐng)求,服務(wù)的主邏輯無(wú)法執(zhí)行。該服務(wù)如果有相應(yīng)的降級(jí)方法則執(zhí)行降級(jí)方法,否則直接拋出錯(cuò)誤響應(yīng)
          • Half-Open:半開狀態(tài)。處于該狀態(tài)時(shí),其會(huì)允許一部分請(qǐng)求流量通過(guò),嘗試執(zhí)行主邏輯。如果發(fā)現(xiàn)調(diào)用成功則說(shuō)明當(dāng)前服務(wù)可以被恢復(fù),進(jìn)而變?yōu)镃losed狀態(tài);否則調(diào)用失敗,繼續(xù)變?yōu)镺pen狀態(tài)

          從上可以看到,正是由于Half-Open狀態(tài)的存在,為服務(wù)的自我恢復(fù)提供了一種思路。關(guān)于上述三種狀態(tài)的轉(zhuǎn)換邏輯,如下所示。在服務(wù)初始階段,斷路器肯定處于Closed狀態(tài)。在斷路器統(tǒng)計(jì)的滑動(dòng)時(shí)間窗口內(nèi),滿足一定的打開條件時(shí),斷路器才會(huì)進(jìn)入Open狀態(tài)。當(dāng)斷路器進(jìn)入Open狀態(tài)達(dá)到一定時(shí)間后會(huì)進(jìn)入Half-Open狀態(tài),讓一部分請(qǐng)求通過(guò)以驗(yàn)證服務(wù)是否可以被恢復(fù),并根據(jù)驗(yàn)證結(jié)果決定進(jìn)入Closed或Open狀態(tài)

          figure 2.jpeg

          這里需要補(bǔ)充說(shuō)明的是,斷路器統(tǒng)計(jì)的滑動(dòng)時(shí)間窗口可通過(guò) metrics.rollingStats.timeInMilliseconds 進(jìn)行配置。而斷路器的打開條件則是指在該時(shí)間窗口內(nèi),其接受的請(qǐng)求數(shù)、請(qǐng)求的失敗率均達(dá)到閾值。需要注意的是,這兩個(gè)閾值必須同時(shí)滿足。可分別通過(guò) circuitBreaker.requestVolumeThresholdcircuitBreaker.errorThresholdPercentage 進(jìn)行配置。最后,對(duì)于斷路器在進(jìn)入Open狀態(tài)后需要多長(zhǎng)時(shí)間才會(huì)進(jìn)入Half-Open狀態(tài),則可通過(guò) circuitBreaker.sleepWindowInMilliseconds 進(jìn)行配置

          為了方便驗(yàn)證測(cè)試,我們?cè)赑aymentController2類繼續(xù)添加一個(gè)新的方法test4

          @RestController
          @RequestMapping("pay2")
          //?該類默認(rèn)的降級(jí)配置
          @DefaultProperties(defaultFallback?=?"defaultFallback")
          public?class?PaymentController2?{

          ????...

          ????@GetMapping("/test4")
          ????@HystrixCommand(?commandProperties?=?{
          ????????//?打開斷路器
          ????????@HystrixProperty(name?=?"circuitBreaker.enabled",?value?=?"true"),
          ????????//?斷路器統(tǒng)計(jì)的滑動(dòng)時(shí)間窗口,?Unit:?ms
          ????????@HystrixProperty(name?=?"metrics.rollingStats.timeInMilliseconds",?value?=?"10000"),
          ????????//?斷路器的請(qǐng)求數(shù)閾值
          ????????@HystrixProperty(name?=?"circuitBreaker.requestVolumeThreshold",?value?=?"5"),
          ????????//?斷路器的請(qǐng)求失敗率閾值,?Unit:?%
          ????????@HystrixProperty(name?=?"circuitBreaker.errorThresholdPercentage",?value?=?"70"),
          ????????//?斷路器進(jìn)入Open打開狀態(tài)多長(zhǎng)時(shí)間后,?允許再次嘗試處理部分請(qǐng)求(即Half-Open半開狀態(tài)),?Unit:?ms
          ????????@HystrixProperty(name?=?"circuitBreaker.sleepWindowInMilliseconds",?value?=?"10000")
          ????})
          ????public?String?test4(@RequestParam?Integer?num)?{
          ????????if(num?50)?{
          ????????????throw?new?RuntimeException("非法參數(shù)異常");
          ????????}

          ????????String?msg?=?"[Payment?Service?-?test4],?num:"?+?num;
          ????????return?msg;
          ????}

          ????/**
          ?????*?默認(rèn)降級(jí)方法
          ?????*?@return
          ?????*/

          ????public?String?defaultFallback()?{
          ????????return?"payment服務(wù)暫不可用";
          ????}

          }

          測(cè)試結(jié)果如下所示。第①次訪問時(shí),可以看到訪問正常,執(zhí)行了主流程;第②次訪問時(shí),發(fā)送了5個(gè)請(qǐng)求且訪問結(jié)果均失敗被降級(jí);然后馬上開始第③次訪問,從測(cè)試結(jié)果可以看出由于該服務(wù)已經(jīng)被熔斷了,直接走降級(jí)方法;等過(guò)了一段時(shí)間后,服務(wù)恢復(fù)第④次訪問成功

          figure 3.jpeg

          服務(wù)限流

          Hystrix提供了兩種隔離策略:線程池隔離、信號(hào)量隔離。這里我們以前者為例介紹如何進(jìn)行限流,信號(hào)量隔離同理。在線程池隔離的場(chǎng)景下,可通過(guò)控制線程池相關(guān)參數(shù)實(shí)現(xiàn)流量控制。這樣當(dāng)線程池資源不足時(shí),對(duì)于新的請(qǐng)求就進(jìn)行降級(jí)。為了方便驗(yàn)證測(cè)試,我們?cè)赑aymentController2類繼續(xù)添加一個(gè)新的方法test5

          @RestController
          @RequestMapping("pay2")
          //?該類默認(rèn)的降級(jí)配置
          @DefaultProperties(defaultFallback?=?"defaultFallback")
          public?class?PaymentController2?{

          ????...
          ????
          ????@GetMapping("/test5")
          ????@HystrixCommand(
          ????????commandProperties?=?{
          ????????????//?方法超時(shí)配置,?Unit:?ms
          ????????????@HystrixProperty(name?=?"execution.isolation.thread.timeoutInMilliseconds",?value?=?"15000"),
          ????????????//?資源隔離模式:?線程池隔離
          ????????????@HystrixProperty(name?=?"execution.isolation.strategy",?value?=?"THREAD")
          ????????},
          ????????threadPoolProperties?=?{
          ????????????//?核心線程數(shù)
          ????????????@HystrixProperty(name?=?"coreSize",?value?=?"2"),
          ????????????//?等待隊(duì)列容量,?-1表示不啟用
          ????????????@HystrixProperty(name?=?"maxQueueSize",?value?=?"-1")
          ????????}
          ????)
          ????public?String?test5(@RequestParam?Integer?num)?{
          ????????if(num?50)?{
          ????????????throw?new?RuntimeException("非法參數(shù)異常");
          ????????}

          ????????//?模擬業(yè)務(wù)耗時(shí)
          ????????try?{
          ????????????Thread.sleep(?10000?);
          ????????}?catch?(Exception?e)?{
          ????????}

          ????????String?msg?=?"[Payment?Service?-?test5],?num:"?+?num;
          ????????return?msg;
          ????}

          ????/**
          ?????*?默認(rèn)降級(jí)方法
          ?????*?@return
          ?????*/

          ????public?String?defaultFallback()?{
          ????????return?"payment服務(wù)暫不可用";
          ????}

          }

          對(duì)于該服務(wù)接口其最大并發(fā)量為2。這樣同時(shí)發(fā)送3個(gè)請(qǐng)求時(shí),可以看到前2個(gè)請(qǐng)求正常處理。但第3個(gè)請(qǐng)求由于(線程池)資源不足被限流了,故進(jìn)行降級(jí)處理。測(cè)試結(jié)果符合預(yù)期

          figure 4.jpeg

          服務(wù)監(jiān)控

          Hystrix還提供了Dashboard以便通過(guò)可視化的方式實(shí)現(xiàn)服務(wù)監(jiān)控。這里我們建立一個(gè)HystrixDashboard服務(wù)對(duì)目標(biāo)服務(wù)進(jìn)行監(jiān)控。首先在POM中我們引入 spring-cloud-starter-netflix-hystrix-dashboard 依賴,如下所示

          <dependencyManagement>
          ??<dependencies>

          ????
          ????<dependency>
          ??????<groupId>org.springframework.bootgroupId>
          ??????<artifactId>spring-boot-dependenciesartifactId>
          ??????<version>2.2.2.RELEASEversion>
          ??????<type>pomtype>
          ??????<scope>importscope>
          ????dependency>

          ????
          ????<dependency>
          ??????<groupId>org.springframework.cloudgroupId>
          ??????<artifactId>spring-cloud-dependenciesartifactId>
          ??????<version>Hoxton.SR1version>
          ??????<type>pomtype>
          ??????<scope>importscope>
          ????dependency>

          ??dependencies>
          dependencyManagement>

          <dependencies>
          ??
          ??
          ??<dependency>
          ??????<groupId>org.springframework.cloudgroupId>
          ??????<artifactId>spring-cloud-starter-netflix-hystrix-dashboardartifactId>
          ??dependency>

          ??
          ??<dependency>
          ??????<groupId>org.springframework.bootgroupId>
          ??????<artifactId>spring-boot-starter-webartifactId>
          ??dependency>

          dependencies>

          然后為該服務(wù)添加一個(gè)啟動(dòng)類即可,并通過(guò)添加@EnableHystrixDashboard注解實(shí)現(xiàn)Hystrix Dashboard的啟用

          @SpringBootApplication
          //?啟用?Hystrix?Dashboard
          @EnableHystrixDashboard
          public?class?HystrixDashboardApplication?{
          ????public?static?void?main(String[]?args)?{
          ????????SpringApplication.run(HystrixDashboardApplication.class,?args);
          ????}
          }

          對(duì)于HystrixDashboard服務(wù)而言,其配置文件如下所示

          spring:
          ??application:
          ????name:?HystrixDashboard

          server:
          ??port:?9111

          這里我們以監(jiān)控payment服務(wù)為例展開說(shuō)明,在此之前我們需要對(duì)被監(jiān)控服務(wù)payment進(jìn)行一些必要的配置。首先需要在POM文件中添加 spring-boot-starter-actuator 依賴

          <dependencies>
          ??
          ??
          ??<dependency>
          ????<groupId>org.springframework.bootgroupId>
          ????<artifactId>spring-boot-starter-actuatorartifactId>
          ????<version>2.2.2.RELEASEversion>
          ??dependency>

          dependencies>

          與此同時(shí),需要配置Actuator以開啟 hystrix.stream 端點(diǎn),相關(guān)配置如下所示

          #?Actuator配置:?開啟?hystrix.stream?端點(diǎn)
          management:
          ??endpoints:
          ????web:
          ??????exposure:
          ????????include:?hystrix.stream
          ??????base-path:?/actuator

          啟動(dòng)payment、HystrixDashboard服務(wù),分別使用8006、9111端口。首先訪問payment服務(wù)的 hystrix.stream 端點(diǎn)驗(yàn)證是否有相關(guān)監(jiān)控?cái)?shù)據(jù),打開 http://localhost:8006/actuator/hystrix.stream 頁(yè)面。效果如下,符合預(yù)期

          figure 5.jpeg

          然后訪問HystrixDashboard服務(wù),打開 http://localhost:9111/hystrix 頁(yè)面。并在頁(yè)面上填寫被監(jiān)控服務(wù)的 hystrix.stream 端點(diǎn)地址、延遲時(shí)間、被監(jiān)控服務(wù)名稱

          figure 6.jpeg

          最后,點(diǎn)擊Monitor Stream開啟監(jiān)控,效果如下所示

          figure 7.jpeg

          參考文獻(xiàn)

          1. Spring微服務(wù)實(shí)戰(zhàn) John Carnell著
          瀏覽 28
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  欧美成人精品三级网站 | 欧美三级午夜理伦三级老人 | 99热在线看| 色婷婷精品在线播放 | 天天日天天操心 |