Spring Cloud Hystrix

功能

  • 服務降級
    • 優先核心服務,非核心服務弱可用或不可用
    • 具體表現爲當調用一個服務不可用或者發生異常時,轉到指定降級頁面或觸發降級信息
    • 通過@HystrixCommand註解指定
    • fallackMethod(回退函數)中實現降級的邏輯
      • 目標服務不可用--降級
      • 本服務出現異常(比如數據庫連接過多,或訪問量太大)--也可以選擇降級
  • 服務熔斷
    • 某個服務的錯誤率到達一定閾值,切斷服務
    • 當斷路器打開,而服務不可用時,休眠時間窗就開始計時,計時結束後,將熔斷器設爲半打開,嘗試發一次請求,若請求成功,關閉熔斷器;若失敗,休眠時間窗繼續計時
  • 依賴隔離
    • 爲每個方法設立一個線程池用於隔離
  • 監控(Hystrix Dashboard)

集成

pom引入依賴

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

啓動類添加註解

@EnableCircuitBreaker

服務降級

A服務訪問B服務,B服務不可用時,觸發降級,轉到某靜態頁面如提示"太擁擠了,請稍後再試"

新建 HystrixController 測試

package com.viki.order.controller;

import com.netflix.hystrix.contrib.javanica.annotation.DefaultProperties;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import java.util.Arrays;

/**
 * @Author Sakura
 * @Date 14/11/2019
 **/
@RestController
public class HystrixController {

    //超時配置
    @HystrixCommand(fallbackMethod = "fallback")  //回調方法名
    @GetMapping("/getProductInfoList")
    public String getProductInfoList() {
  
        //使用RestTemplate 調用其他服務方法名
        RestTemplate restTemplate = new RestTemplate();
        return restTemplate.postForObject("http://127.0.0.1:8090/product/listForOrder",
                Arrays.asList("10"),
                String.class);

    }

    private String fallback() {
        return "太擁擠了, 請稍後再試~~";
    }
}

也可以指定默認方法

package com.viki.order.controller;

import com.netflix.hystrix.contrib.javanica.annotation.DefaultProperties;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import java.util.Arrays;

/**
 * @Author Sakura
 * @Date 14/11/2019
 **/
@RestController
@DefaultProperties(defaultFallback = "defaultFallback")
public class HystrixController {

    //超時配置
    @HystrixCommand
    @GetMapping("/getProductInfoList")
    public String getProductInfoList() {
  
        //使用RestTemplate 調用其他服務方法名
        RestTemplate restTemplate = new RestTemplate();
        return restTemplate.postForObject("http://127.0.0.1:8090/product/listForOrder",
                Arrays.asList("10"),
                String.class);

    }

    private String defaultFallback() {
        return "默認提示:太擁擠了, 請稍後再試~~";
    }
}

超時時間配置

默認超時時間是1秒,即在一秒鐘之內無法收到返回的結果就會降級。而許多服務的運行時間確實長,所以需要更改超時時間

@HystrixCommand(commandProperties = {
            @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "3000")
    })

使用配置項設置

在方法加註解@HystrixCommand的前提下,配置文件中配置

hystrix:
  command:
    default:
      execution:
        isolation:
          thread:
            timeoutInMilliseconds: 1000
    getProductInfoList:
      execution:
        isolation:
          thread:
            timeoutInMilliseconds: 3000

可使用default統一設置,也可以爲具體的方法具體設置,如getProductInfoList

feign-hystrix的使用

配置添加

feign:
  hystrix:
    enabled: true

啓動類添加掃描使Feign的包被掃描到

@ComponentScan(basePackages = "com.viki")

Feignclient的配置更改

@FeignClient(name = "product", fallback = ProductClient.ProductClientFallback.class)
public interface ProductClient {

    @PostMapping("/product/listForOrder")
    List<ProductInfoOutput> listForOrder(@RequestBody List<String> productIdList);

    @PostMapping("/product/decreaseStock")
    void decreaseStock(@RequestBody List<DecreaseStockInput> decreaseStockInputList);

    //降級回調函數
    @Component
    static class ProductClientFallback implements ProductClient{

        @Override
        public List<ProductInfoOutput> listForOrder(List<String> productIdList) {
            return null;
        }

        @Override
        public void decreaseStock(List<DecreaseStockInput> decreaseStockInputList) {

        }
    }
}

依賴隔離

Hystrix使用倉壁模式實現了線程池的隔離,會爲每個HystrixCommand創建一個獨立的線程池,各HystrixCommand之前互相隔離,不會相互影響,自動實現依賴隔離。

服務降級和依賴隔離是一體化實現的

服務熔斷

@HystrixCommand(commandProperties = {
            @HystrixProperty(name = "circuitBreaker.enabled", value = "true"),  //設置熔斷
            @HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value = "10"), //在滾動時間窗口中斷路器最小請求數
            @HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds", value = "10000"), //休眠時間窗計時時間
            @HystrixProperty(name = "circuitBreaker.errorThresholdPercentage", value = "60") //失敗率,高於此則打開斷路器
    })

主要有4個參數,以上都有註釋

整體的效果是:在10秒鐘之內,若請求數大於等於10次,其中失敗率達到60%,即失敗超過6次,熔斷器就會開啓。此時就會觸發降級。

10秒鐘結束後,自動發一次請求,若成功,則關閉熔斷器,請求會正常;若失敗,熔斷器保持打開,服務降級。

package com.viki.order.controller;

import com.netflix.hystrix.contrib.javanica.annotation.DefaultProperties;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import java.util.Arrays;

/**
 * @Author Sakura
 * @Date 14/11/2019
 **/
@RestController
@DefaultProperties(defaultFallback = "defaultFallback")
public class HystrixController {

    //當斷路器打開,服務不可用,休眠時間窗就開始計時,計時結束後,將熔斷器設爲半打開,嘗試發一次請求,若請求成功,關閉熔斷器;若失敗,休眠時間窗繼續計時
    @HystrixCommand(commandProperties = {
            @HystrixProperty(name = "circuitBreaker.enabled", value = "true"),  //設置熔斷
            @HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value = "10"), //在滾動時間窗口中斷路器最小請求數
            @HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds", value = "10000"), //休眠時間窗計時時間
            @HystrixProperty(name = "circuitBreaker.errorThresholdPercentage", value = "60") //失敗率,高於此則打開斷路器
    })
    @GetMapping("/getProductInfoList")
    public String getProductInfoList(@RequestParam("number") Integer number) {
        if(number%2 == 0){
            return "success";
        }

        RestTemplate restTemplate = new RestTemplate();
        return restTemplate.postForObject("http://127.0.0.1:8090/product/listForOrder",
                Arrays.asList("10"),
                String.class);

    }

    private String defaultFallback() {
        return "默認提示:太擁擠了, 請稍後再試~~";
    }
}

請求必須攜帶number參數,若number爲偶數,就直接訪問成功,顯示爲success;若number爲奇數,就調用服務,此時服務未啓動,便失敗觸發降級。

http://localhost:8081/getProductInfoList?number=1 失敗

http://localhost:8081/getProductInfoList?number=2 成功

不斷訪問失敗鏈接,一直快速訪問。此時在訪問成功鏈接,也出現了降級,失敗

Dashboard界面查看熔斷

pom引入依賴

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

啓動類添加註解

@EnableHystrixDashboard

打開上方提到的熔斷器,啓動項目後網頁輸入 http://localhost:8081/hystrix 

URL輸入 http://localhost:8081/actuator/hystrix.stream

Delay延時設置爲2000

Title應用名稱設置爲Order

點擊Monitor Stream

此時訪問上述兩個鏈接之一纔會顯示儀表盤

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章