Sentinal(三)流量控制與熔斷降級

Sentinel以流量爲切入點,以流量控制、熔斷降級、系統負載保護等多個維度保護服務的穩定性。包括核心的獨立類庫、監控臺、豐富的使用場景。

使用場景:秒殺(即突發流量控制在系統容量可以承受的範圍)、消息削峯填谷、實時熔斷下游不可用應用等。

實時監控,開源生態(開箱即用且與其他開源框架/庫的整合模塊),完善的SPI擴展點(實現擴展,快速定製邏輯,如定製規則邏輯、適配數據流等)

  1. 資源管理:應用服務器腳本、靜態頁面、API接口、文件圖片等
  2. 規則配置:允許資源(一般API接口)通過的請求次數,IP黑白名單,應用服務等
  3. 測試效果:QPS(單臺服務器每秒能處理查詢次數);TPS(每秒處理的事務數,傾向整個過程)

Sentinel分爲兩部分:

  • 核心庫(JAVA客戶端)不依賴任何框架/庫
  • 控制檯(Dashboard)基於Spring boot開發,打包直接運行(不需要額外tomcat等應用容器,該模塊目前基於Spring boot運行)

# 下面開始整合框架:Nacos註冊中心、Feign服務、Sentinel哨兵、Sentinel控制檯

一、Sentinel入門介紹

# 搭建2.2.5.RELEASE(與上一文搭建Nacos選了1.4.1版本)sentinel按下圖選擇的1.8.0版本,下載地址:https://github.com/alibaba/Sentinel/releases

下載到本地後,執行 javaw -jar sentinel-dashboard-1.8.0.jar 默認端口8080( 如果8080端口被佔用,可以自定義啓動端口java -jar xxx.jar --server.port=8888)linux 後臺啓動可以執行 nohup java -jar xxx.jar >log.log & 指定日誌文件位置和後臺掛起啓動

啓動成功後訪問地址:http://ip:port 默認用戶名密碼:sentinel

二、搭建Sentinel項目

現在創建一個cloudalbb-sentinel-ribbon1020項目,項目裏基本依賴和配置如下:

        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
        </dependency>
server:
  port: 1020


spring:
  application:
    name: sentinel-ribbon1020
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848 #nacos集羣,使用的是域名
    sentinel:
      transport:
        dashboard: localhost:8080 #配置sentinel dashboard地址
        port: 8719 #默認8719端口

service-url:
  nacos-service: http://nacos-provider

1、只配置單個blockHandler限流降速處理方法配置

 @GetMapping("/request/pay/{id}")
 @SentinelResource(value = "fallback",blockHandler = "blockHandler") //blockHandler只負責sentinel控制檯配置違規
    public CommonResult<Order> reqToPay(@PathVariable("id") Long id){

        CommonResult<Order> result = restTemplate.getForObject(serverURL+"/order/"+id, CommonResult.class);

        return result;
    }


    public CommonResult<Order> blockHandler(@PathVariable("id") Long id, BlockException exception){
        // 不同的異常返回不同的提示語
        String reason = "";
        if (exception instanceof FlowException) {
            reason = "接口限流了";
        } else if (exception instanceof DegradeException) {
            reason = "服務降級了";
        } else if (exception instanceof ParamFlowException) {
            reason = "熱點參數限流了";
        } else if (exception instanceof SystemBlockException) {
            reason = "觸發系統保護規則";
        } else if (exception instanceof AuthorityException) {
            reason = "授權規則不通過";
        }
        Order order = new Order(id, "默認值");
        return new CommonResult<Order>(521, "收到請求id:"+id+",sentinel-blockHandler"+reason+":"+exception.getMessage(), order);
    }

將nacos-provider和sentinel-ribbon2010兩個項目啓動,然後配置流量降速,最後訪問一下

2、加個blockHandlerClass限流降級處理類配置

爲了提高代碼的可讀性及解耦,將自定義限流降速方法寫入一個限流降速級類中,需要時再調用(所有的方法均爲static靜態方法,參數必須帶上BlockException,否則找不到響應方法), blockHandler 函數訪問範圍需要是 public,返回類型需要與原方法相匹配,參數類型需要和原方法相匹配並且最後加一個額外的參數,類型爲 BlockException blockHandler 函數默認需要和原方法在同一個類中。若希望使用其他類的函數,則可以指定 blockHandlerClass 爲對應的類的 Class 對象,注意對應的函數必需爲 static 函數,否則無法解析

@GetMapping("/request/pay/{id}")
@SentinelResource(value = "fallback",blockHandler = "blockHandler",blockHandlerClass = BlockHandler.class) //blockHandler只負責sentinel控制檯配置違規
    public CommonResult<Order> reqToPay(@PathVariable("id") Long id){

        CommonResult<Order> result = restTemplate.getForObject(serverURL+"/order/"+id, CommonResult.class);

        return result;
    }

3、只配置單個fallback熔斷降級方法配置

defaultFallback,默認的 fallback 函數名稱,可選項,通常用於通用的 fallback 邏輯(即可以用於很多服務或方法)。默認 fallback 函數可以針對所有類型的異常(除了 exceptionsToIgnore 裏面排除掉的異常類型)進行處理。若同時配置了 fallback 和 defaultFallback,則只有 fallback 會生效。

@GetMapping("/request/pay/{id}")
@SentinelResource(value = "fallback",fallback = "handlerFallback") //fallback只負責業務異常
    public CommonResult<Order> reqToPay(@PathVariable("id") Long id){

        CommonResult<Order> result = restTemplate.getForObject(serverURL+"/order/"+id, CommonResult.class);

        int test = 10/0;

        return result;
    }

    public CommonResult<Order> handlerFallback(@PathVariable("id") Long id, Throwable throwable){
        Order order = new Order(id, "默認值");
        return new CommonResult<Order>(520, "收到請求id:"+id+",業務異常:"+throwable.getMessage(), order);
    }

4、加個fallbackClass熔斷降級處理類配置

@GetMapping("/request/pay/{id}")
@SentinelResource(value = "fallback",fallback = "handlerFallback",fallbackClass=CustomerFallback.class) //fallback只負責業務異常
    public CommonResult<Order> reqToPay(@PathVariable("id") Long id){

        CommonResult<Order> result = restTemplate.getForObject(serverURL+"/order/"+id, CommonResult.class);

        int test = 10/0;

        return result;
    }

    public CommonResult<Order> handlerFallback(@PathVariable("id") Long id, Throwable throwable){
        Order order = new Order(id, "默認值");
        return new CommonResult<Order>(520, "收到請求id:"+id+",業務異常:"+throwable.getMessage(), order);
    }

5、blockHandler和fallback可以同時配置,不再贅述

exceptionsToIgnore,用於指定哪些異常被排除掉,不會計入異常統計中,也不會進入 fallback 邏輯中,而是會原樣拋出。

 @GetMapping("/request/pay/{id}")
//    blockHandler/blockHandlerClass流速降級,fallback/fallbackClass熔斷降速
//    @SentinelResource(value="fallback") //無配置
//    @SentinelResource(value = "fallback",fallback = "handlerFallback") //fallback只負責業務異常
//    @SentinelResource(value = "fallback",fallback = "customerFallback",fallbackClass = CustomerFallback.class) //獨立的業務異常處理
//    @SentinelResource(value = "fallback",defaultFallback = "defaultFallback") //通常用於通用的 fallback 邏輯(即可以用於很多服務或方法)
//    @SentinelResource(value = "fallback",defaultFallback = "customerDefaultFallback",fallbackClass = DefaultFallBack.class) //通常用於通用的 fallback 邏輯(即可以用於很多服務或方法)
//    @SentinelResource(value = "fallback",blockHandler = "blockHandler") //blockHandler只負責sentinel控制檯配置違規
    @SentinelResource(value = "fallback",fallback = "handlerFallback",blockHandler = "blockHandler", exceptionsToIgnore = {IllegalArgumentException.class} )  //異常被排除掉,不會進入fallback邏輯中,而是會原樣拋出。
    public CommonResult<Order> reqToPay(@PathVariable("id") Long id){

        CommonResult<Order> result = restTemplate.getForObject(serverURL+"/order/"+id, CommonResult.class);

        int test = 10/0;

        return result;
    }

三、集成Spring Cloud OpenFeign

Service層進行註解配置:

@FeignClient(value = "nacos-provider",fallback = PaymentFallbackServiceImpl.class)
@Component
public interface PaymentService {

    @GetMapping("/order/{id}")
    public CommonResult<Order> getOrderById(@PathVariable("id")Long id);
}
@Component
public class PaymentFallbackServiceImpl implements PaymentService {

    @Override
    public CommonResult<Order> getOrderById(Long id) {
        return new CommonResult<>(444,"服務降級返回,OrderFallbackService",new Order(id,"errorSerial"));
    }
}

四、集成RestTemplate

@Bean
@LoadBalanced
@SentinelRestTemplate(blockHandler = "handleException", blockHandlerClass = ExceptionUtil.class)
public RestTemplate restTemplate() {
    return new RestTemplate();
}

@SentinelRestTemplate 註解的屬性支持限流(blockHandler, blockHandlerClass)和降級(fallback, fallbackClass)的處理。

其中 blockHandler 或 fallback 屬性對應的方法必須是對應 blockHandlerClass 或 fallbackClass 屬性中的靜態方法。

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