Spring Cloud 熔斷降級

1扒腕、 什么是熔斷

一般是某個服務(wù)故障或者是異常引起的擂达,類似現(xiàn)實世界中的‘保險絲’土铺,當(dāng)某個異常條件被觸發(fā),直接熔斷整個服務(wù)板鬓,而不是一直等到此服務(wù)超時悲敷,為了防止防止整個系統(tǒng)的故障,而采用了一些保護措施俭令。過載保護后德。
比如A服務(wù)的X功能依賴B服務(wù)的某個接口,當(dāng)B服務(wù)接口響應(yīng)很慢時唤蔗,A服務(wù)X功能的響應(yīng)也會被拖慢探遵,進一步導(dǎo)致了A服務(wù)的線程都卡在了X功能上,A服務(wù)的其它功能也會卡主或拖慢妓柜。此時就需要熔斷機制箱季,即A服務(wù)不在請求B這個接口,而可以直接進行降級處理棍掐。

2藏雏、 什么是降級

服務(wù)器當(dāng)壓力劇增的時候,根據(jù)當(dāng)前業(yè)務(wù)情況及流量作煌,對一些服務(wù)和頁面進行有策略的降級掘殴。以此緩解服務(wù)器資源的的壓力,以保證核心業(yè)務(wù)的正常運行粟誓,同時也保持了客戶和大部分客戶的得到正確的相應(yīng)奏寨。

3、熔斷和降級異同

相同點:
1.從可用性和可靠性觸發(fā)鹰服,為了防止系統(tǒng)崩潰
2.最終讓用戶體驗到的是某些功能暫時不能用
不同點:
1.服務(wù)熔斷一般是下游服務(wù)故障導(dǎo)致的病瞳,而服務(wù)降級一般是從整體系統(tǒng)負荷考慮,由調(diào)用方控制悲酷。

4套菜、Netflix開源組件斷路器Hystrix

文檔地址:
https://github.com/Netflix/Hystrix

為什么用Hystrix

在一個分布式系統(tǒng)里,一個服務(wù)依賴多個服務(wù)设易,可能存在某個服務(wù)調(diào)用失敗逗柴,比如超時、異常等顿肺,如何能夠保證在一個依賴出問題的情況下戏溺,不會導(dǎo)致整體服務(wù)失敗渣蜗,通過Hystrix就可以解決。

Hystrix是如何實現(xiàn)它的目標(biāo)的

(1)通過HystrixCommand或者HystrixObservableCommand來封裝對外部依賴的訪問請求于购,這個訪問請求一般會運行在獨立的線程中钓试,資源隔離
(2)對于超出我們設(shè)定閾值的服務(wù)調(diào)用芽卿,直接進行超時,不允許其耗費過長時間阻塞住鞠抑。這個超時時間默認是99.5%的訪問時間控淡,但是一般我們可以自己設(shè)置一下
(3)為每一個依賴服務(wù)維護一個獨立的線程池嫌吠,或者是semaphore,當(dāng)線程池已滿時掺炭,直接拒絕對這個服務(wù)的調(diào)用
(4)對依賴服務(wù)的調(diào)用的成功次數(shù)辫诅,失敗次數(shù),拒絕次數(shù)涧狮,超時次數(shù)炕矮,進行統(tǒng)計
(5)如果對一個依賴服務(wù)的調(diào)用失敗次數(shù)超過了一定的閾值,自動進行熔斷者冤,在一定時間內(nèi)對該服務(wù)的調(diào)用直接降級肤视,一段時間后再自動嘗試恢復(fù)
(6)當(dāng)一個服務(wù)調(diào)用出現(xiàn)失敗,被拒絕涉枫,超時邢滑,短路等異常情況時,自動調(diào)用fallback降級機制
(7)對屬性和配置的修改提供近實時的支持

5愿汰、Hystrix實戰(zhàn)

使用到的組件包括:Eureka困后、Feign包括以下三個項目:
(1)Eureka-server: 注冊中心
(2)product-service :商品微服務(wù)
(3)order-service: 訂單微服務(wù)
前面文章已經(jīng)搭建過 這里不做贅述 這里只寫order-service微服務(wù)
pom.xml 添加依賴

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

application.yml

server:
  port: 8781

#指定注冊中心地址
eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:7001/eureka/

#服務(wù)的名稱
spring:
  application:
    name: order-service
    
#開啟feign支持hystrix  (注意,一定要開啟衬廷,舊版本默認支持摇予,新版本默認關(guān)閉)
# #修改調(diào)用超時時間(默認是1秒就算超時)
feign:
  hystrix:
    enabled: true
  client:
    config:
      default:
        connectTimeout: 2000
        readTimeout: 2000
#hystrix超時時間調(diào)整(默認是一秒)
hystrix:
  command:
    default:
      execution:
        isolation:
          thread:
            timeoutInMilliseconds: 2000

SpringBoot啟動類

@SpringBootApplication
@EnableFeignClients
//添加熔斷降級注解
@EnableCircuitBreaker
public class OrderServiceApplication {

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

}

ProductClient

/**
 * 商品服務(wù)客戶端
 * name = "product-service"是你調(diào)用服務(wù)端名稱
 * fallback = ProductClientFallback.class,后面是你自定義的降級處理類吗跋,降級類一定要實現(xiàn)ProductClient
 */
@FeignClient(name = "product-service",fallback = ProductClientFallback.class)
public interface ProductClient {

    //這樣組合就相當(dāng)于http://product-service/api/v1/product/find
    @GetMapping("/api/v1/product/find")
    String findById(@RequestParam(value = "id") int id);

}

ProductClientFallback降級處理類

/**
 * 針對商品服務(wù)侧戴,錯降級處理
 */
@Component
public class ProductClientFallback implements ProductClient {

    @Override
    public String findById(int id) {

        System.out.println("ProductClientFallback中的降級方法");

        //這對gai該接口進行一些邏輯降級處理........
        return null;
    }
}

OrderController類
注意:fallbackMethod = "saveOrderFail"中的saveOrderFail方法中的參數(shù)類型,個數(shù)小腊,順序要和save一模一樣救鲤,否則會報找不到saveOrderFail方法。

@RestController
@RequestMapping("api/v1/order")
public class OrderController {

    @Autowired
    private ProductOrderService productOrderService;

    @RequestMapping("save")
    //當(dāng)調(diào)用微服務(wù)出現(xiàn)異常會降級到saveOrderFail方法中
    @HystrixCommand(fallbackMethod = "saveOrderFail")
    public Object save(@RequestParam("user_id")int userId, @RequestParam("product_id") int productId){

        return productOrderService.save(userId, productId);
    }

    //注意秩冈,方法簽名一定要要和api方法一致
    private Object saveOrderFail(int userId, int productId){

        System.out.println("controller中的降級方法");

        Map<String, Object> msg = new HashMap<>();
        msg.put("code", -1);
        msg.put("msg", "搶購人數(shù)太多本缠,您被擠出來了,稍等重試");
        return msg;
    }
}

測試

正常情況時如圖:
訂單服務(wù)調(diào)用商品服務(wù)正常

異常情況

此刻商品微服務(wù)停掉:只啟動訂單微服務(wù)入问,這時去調(diào)用商品服務(wù)當(dāng)然會出現(xiàn)超時異常情況在調(diào)接口丹锹,發(fā)現(xiàn)已經(jīng)成功到降級方法里
在看controller中的降級方法和ProductClientFallback降級方法的實現(xiàn)先后順序稀颁,它們的順序是不固定的,具體要看哪個線程先獲得cpu執(zhí)行權(quán)

6楣黍、結(jié)合redis模擬熔斷降級服務(wù)異常報警通知實戰(zhàn)

主要是完善服務(wù)熔斷處理匾灶,報警機制完善結(jié)合redis進行模擬短信通知用戶下單失敗。
pom.xml

  <!--springboot整合redis-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>

application.yml

#redis
spring:
  application:
    name: order-service
  redis:
    database: 0
    host: 127.0.0.1
    port: 6379
    timeout: 2000

OrderController類
主要看降級方法的不同

@RestController
@RequestMapping("api/v1/order")
public class OrderController {

    @Autowired
    private ProductOrderService productOrderService;

    //添加bean
    @Autowired
    private StringRedisTemplate redisTemplate;

    @RequestMapping("save")
    //當(dāng)調(diào)用微服務(wù)出現(xiàn)異常會降級到saveOrderFail方法中
    @HystrixCommand(fallbackMethod = "saveOrderFail")
    public Object save(@RequestParam("user_id")int userId, @RequestParam("product_id") int productId,HttpServletRequest request){

        return productOrderService.save(userId, productId);
    }

    //注意租漂,方法簽名一定要要和api方法一致
    private Object saveOrderFail(int userId, int productId, HttpServletRequest request){
        
        //監(jiān)控報警
        String saveOrderKye = "save-order";
        //有數(shù)據(jù)代表20秒內(nèi)已經(jīng)發(fā)過
        String sendValue = redisTemplate.opsForValue().get(saveOrderKye);
        final String ip = request.getRemoteAddr();

        //新啟動一個線程進行業(yè)務(wù)邏輯處理
        new Thread( ()->{
            if (StringUtils.isBlank(sendValue)) {
                System.out.println("緊急短信阶女,用戶下單失敗,請離開查找原因,ip地址是="+ip);
                //發(fā)送一個http請求哩治,調(diào)用短信服務(wù) TODO
                redisTemplate.opsForValue().set(saveOrderKye, "save-order-fail", 20, TimeUnit.SECONDS);

            }else{
                System.out.println("已經(jīng)發(fā)送過短信秃踩,20秒內(nèi)不重復(fù)發(fā)送");
            }
        }).start();

        Map<String, Object> msg = new HashMap<>();
        msg.put("code", -1);
        msg.put("msg", "搶購人數(shù)太多,您被擠出來了业筏,稍等重試");
        return msg;
    }

}

測試

當(dāng)20秒內(nèi)連續(xù)發(fā)請求會提醒已發(fā)短信憔杨。

7、 Dashboard儀表盤監(jiān)控

1蒜胖、加入依賴

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

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>

2消别、啟動類增加注解

   @EnableHystrixDashboard

3、配置文件增加endpoint

#新版本默認不暴露端點 改成暴露全部端點
management:
  endpoints:
    web:
      exposure:
        include: "*"

4台谢、訪問入口

    http://localhost:8781/hystrix
    Hystrix Dashboard輸入: http://localhost:8781/actuator/hystrix.stream 
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末寻狂,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子对碌,更是在濱河造成了極大的恐慌荆虱,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,755評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件朽们,死亡現(xiàn)場離奇詭異怀读,居然都是意外死亡,警方通過查閱死者的電腦和手機骑脱,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評論 3 395
  • 文/潘曉璐 我一進店門菜枷,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人叁丧,你說我怎么就攤上這事啤誊。” “怎么了拥娄?”我有些...
    開封第一講書人閱讀 165,138評論 0 355
  • 文/不壞的土叔 我叫張陵蚊锹,是天一觀的道長。 經(jīng)常有香客問我稚瘾,道長牡昆,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,791評論 1 295
  • 正文 為了忘掉前任摊欠,我火速辦了婚禮丢烘,結(jié)果婚禮上柱宦,老公的妹妹穿的比我還像新娘。我一直安慰自己播瞳,他們只是感情好掸刊,可當(dāng)我...
    茶點故事閱讀 67,794評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著赢乓,像睡著了一般忧侧。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上骏全,一...
    開封第一講書人閱讀 51,631評論 1 305
  • 那天苍柏,我揣著相機與錄音尼斧,去河邊找鬼姜贡。 笑死,一個胖子當(dāng)著我的面吹牛棺棵,可吹牛的內(nèi)容都是我干的楼咳。 我是一名探鬼主播,決...
    沈念sama閱讀 40,362評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼烛恤,長吁一口氣:“原來是場噩夢啊……” “哼母怜!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起缚柏,我...
    開封第一講書人閱讀 39,264評論 0 276
  • 序言:老撾萬榮一對情侶失蹤苹熏,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后币喧,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體轨域,經(jīng)...
    沈念sama閱讀 45,724評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年杀餐,在試婚紗的時候發(fā)現(xiàn)自己被綠了干发。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,040評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡史翘,死狀恐怖枉长,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情琼讽,我是刑警寧澤必峰,帶...
    沈念sama閱讀 35,742評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站钻蹬,受9級特大地震影響吼蚁,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜脉让,卻給世界環(huán)境...
    茶點故事閱讀 41,364評論 3 330
  • 文/蒙蒙 一桂敛、第九天 我趴在偏房一處隱蔽的房頂上張望功炮。 院中可真熱鬧,春花似錦术唬、人聲如沸薪伏。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,944評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽嫁怀。三九已至,卻和暖如春借浊,著一層夾襖步出監(jiān)牢的瞬間塘淑,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,060評論 1 270
  • 我被黑心中介騙來泰國打工蚂斤, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留存捺,地道東北人。 一個月前我還...
    沈念sama閱讀 48,247評論 3 371
  • 正文 我出身青樓曙蒸,卻偏偏與公主長得像捌治,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子纽窟,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,979評論 2 355

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