Sentinel流量控制熔斷降級

Spring Cloud Alibaba Sentinel

Sentinel 介紹

隨着微服務的流行,服務和服務之間的穩定性變得越來越重要。 Sentinel 以流量爲切入點,從流量控制、熔斷降級、系統負載保護等多個維度保護服務的穩定性。

Sentinel 具有以下特徵:

  • 豐富的應用場景: Sentinel 承接了阿里巴巴近 10 年的雙十一大促流量的核心場景,例如秒殺(即突發流量控制在系統容量可以承受的範圍)、消息削峯填谷、實時熔斷下游不可用應用等。
  • 完備的實時監控: Sentinel 同時提供實時的監控功能。您可以在控制檯中看到接入應用的單臺機器秒級數據,甚至 500 臺以下規模的集羣的彙總運行情況。
  • 廣泛的開源生態: Sentinel 提供開箱即用的與其它開源框架/庫的整合模塊,例如與 Spring Cloud、Dubbo、gRPC 的整合。您只需要引入相應的依賴並進行簡單的配置即可快速地接入 Sentinel。
  • 完善的 SPI 擴展點: Sentinel 提供簡單易用、完善的 SPI 擴展點。您可以通過實現擴展點,快速的定製邏輯。例如定製規則管理、適配數據源等。

如何使用 Sentinel

如果要在您的項目中引入 Sentinel,使用 group ID  com.alibaba.cloud  artifact ID  spring-cloud-starter-alibaba-sentinel  starter

<dependency>

    <groupId>com.alibaba.cloud</groupId>

    <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>

</dependency>

下面這個例子就是一個最簡單的使用 Sentinel 的例子:

@SpringBootApplication

public class Application {

    public static void main(String[] args) {

        SpringApplication.run(ServiceApplication.class, args);

    }

}



@Service

public class TestService {

    @SentinelResource(value = "sayHello")

    public String sayHello(String name) {

        return "Hello, " + name;

    }

}



@RestController

public class TestController {

    @Autowired

    private TestService service;


    @GetMapping(value = "/hello/{name}")

    public String apiHello(@PathVariable String name) {

        return service.sayHello(name);

    }

}

@SentinelResource 註解用來標識資源是否被限流、降級。上述例子上該註解的屬性 sayHello 表示資源名。

@SentinelResource 還提供了其它額外的屬性如 blockHandlerblockHandlerClassfallback 用於表示限流或降級的操作(注意有方法簽名要求),更多內容可以參考 Sentinel 註解支持文檔。若不配置 blockHandlerfallback 等函數,則被流控降級時方法會直接拋出對應的 BlockException;若方法未定義 throws BlockException 則會被 JVM 包裝一層 UndeclaredThrowableException

注:一般推薦將 @SentinelResource 註解加到服務實現上,而在 Web 層直接使用 Spring Cloud Alibaba 自帶的 Web 埋點適配。Sentinel Web 適配同樣支持配置自定義流控處理邏輯,參考 相關文檔

以上例子都是在 Web Servlet 環境下使用的。Sentinel 目前已經支持 Spring WebFlux,需要配合 spring-boot-starter-webflux 依賴觸發 sentinel-starter WebFlux 相關的自動化配置。

@SpringBootApplication

public class Application {



    public static void main(String[] args) {

        SpringApplication.run(ServiceApplication.class, args);

    }



}



@RestController

public class TestController {



    @GetMapping("/mono")

    public Mono<String> mono() {

        return Mono.just("simple string");

    }



}

Spring WebFlux 應用接入 Sentinel starter 後,所有的 URL 就自動成爲 Sentinel 中的埋點資源,可以針對某個 URL 進行流控。

Sentinel 控制檯

Sentinel 控制檯提供一個輕量級的控制檯,它提供機器發現、單機資源實時監控、集羣資源彙總,以及規則管理的功能。您只需要對應用進行簡單的配置,就可以使用這些功能。

注意: 集羣資源彙總僅支持 500 臺以下的應用集羣,有大概 1 - 2 秒的延時。

 

Figure 1. Sentinel Dashboard

開啓該功能需要3個步驟:

獲取控制檯

您可以從 release 頁面 下載最新版本的控制檯 jar 包。

您也可以從最新版本的源碼自行構建 Sentinel 控制檯:

  • 下載 控制檯 工程
  • 使用以下命令將代碼打包成一個 fat jar: mvn clean package

啓動控制檯

Sentinel 控制檯是一個標準的 Spring Boot 應用,以 Spring Boot 的方式運行 jar 包即可。

java -Dserver.port=8080 -Dcsp.sentinel.dashboard.server=localhost:8080 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard.jar

如若8080端口衝突,可使用 -Dserver.port=新端口 進行設置。

配置控制檯信息

application.yml

spring:

  cloud:

    sentinel:

      transport:

        port: 8719

        dashboard: localhost:8080

這裏的 spring.cloud.sentinel.transport.port 端口配置會在應用對應的機器上啓動一個 Http Server,該 Server 會與 Sentinel 控制檯做交互。比如 Sentinel 控制檯添加了一個限流規則,會把規則數據 push 給這個 Http Server 接收,Http Server 再將規則註冊到 Sentinel 中。

更多 Sentinel 控制檯的使用及問題參考: Sentinel 控制檯文檔 以及 Sentinel FAQ

Feign 支持

Sentinel 適配了 Feign 組件。如果想使用,除了引入 spring-cloud-starter-alibaba-sentinel 的依賴外還需要 2 個步驟:

  • 配置文件打開 Sentinel 對 Feign 的支持:feign.sentinel.enabled=true
  • 加入 spring-cloud-starter-openfeign 依賴使 Sentinel starter 中的自動化配置類生效:
<dependency>

    <groupId>org.springframework.cloud</groupId>

    <artifactId>spring-cloud-starter-openfeign</artifactId>

</dependency>

這是一個 FeignClient 的簡單使用示例:

@FeignClient(name = "service-provider", fallback = EchoServiceFallback.class, configuration = FeignConfiguration.class)

public interface EchoService {

    @RequestMapping(value = "/echo/{str}", method = RequestMethod.GET)

    String echo(@PathVariable("str") String str);

}



class FeignConfiguration {

    @Bean

    public EchoServiceFallback echoServiceFallback() {

        return new EchoServiceFallback();

    }

}



class EchoServiceFallback implements EchoService {

    @Override

    public String echo(@PathVariable("str") String str) {

        return "echo fallback";

    }

}

Note

Feign 對應的接口中的資源名策略定義:httpmethod:protocol://requesturl。@FeignClient註解中的所有屬性,Sentinel 都做了兼容。

EchoService 接口中方法 echo 對應的資源名爲 GET:http://service-provider/echo/{str}

RestTemplate 支持

Spring Cloud Alibaba Sentinel 支持對 RestTemplate 的服務調用使用 Sentinel 進行保護,在構造 RestTemplate bean的時候需要加上 @SentinelRestTemplate 註解。

@Bean

@SentinelRestTemplate(blockHandler = "handleException", blockHandlerClass = ExceptionUtil.class)

public RestTemplate restTemplate() {

    return new RestTemplate();

}

@SentinelRestTemplate 註解的屬性支持限流(blockHandlerblockHandlerClass)和降級(fallbackfallbackClass)的處理。

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

該方法的參數跟返回值跟 org.springframework.http.client.ClientHttpRequestInterceptor#interceptor 方法一致,其中參數多出了一個 BlockException 參數用於獲取 Sentinel 捕獲的異常。

比如上述 @SentinelRestTemplate 註解中 ExceptionUtil  handleException 屬性對應的方法聲明如下:

public class ExceptionUtil {

    public static ClientHttpResponse handleException(HttpRequest request, byte[] body, ClientHttpRequestExecution execution, BlockException exception) {

        ...

    }

}

Note

應用啓動的時候會檢查 @SentinelRestTemplate 註解對應的限流或降級方法是否存在,如不存在會拋出異常

@SentinelRestTemplate 註解的限流(blockHandlerblockHandlerClass)和降級(fallbackfallbackClass)屬性不強制填寫。

當使用 RestTemplate 調用被 Sentinel 熔斷後,會返回 RestTemplate request block by sentinel 信息,或者也可以編寫對應的方法自行處理返回信息。這裏提供了 SentinelClientHttpResponse 用於構造返回信息。

Sentinel RestTemplate 限流的資源規則提供兩種粒度:

  • httpmethod:schema://host:port/path:協議、主機、端口和路徑
  • httpmethod:schema://host:port:協議、主機和端口

Note

以 https://www.taobao.com/test 這個 url 並使用 GET 方法爲例。對應的資源名有兩種粒度,分別是 GET:https://www.taobao.com 以及 GET:https://www.taobao.com/test

動態數據源支持

SentinelProperties 內部提供了 TreeMap 類型的 datasource 屬性用於配置數據源信息。

比如配置 4 個數據源:

spring.cloud.sentinel.datasource.ds1.file.file=classpath: degraderule.json

spring.cloud.sentinel.datasource.ds1.file.rule-type=flow



#spring.cloud.sentinel.datasource.ds1.file.file=classpath: flowrule.json

#spring.cloud.sentinel.datasource.ds1.file.data-type=custom

#spring.cloud.sentinel.datasource.ds1.file.converter-class=com.alibaba.cloud.examples.JsonFlowRuleListConverter

#spring.cloud.sentinel.datasource.ds1.file.rule-type=flow



spring.cloud.sentinel.datasource.ds2.nacos.server-addr=localhost:8848

spring.cloud.sentinel.datasource.ds2.nacos.data-id=sentinel

spring.cloud.sentinel.datasource.ds2.nacos.group-id=DEFAULT_GROUP

spring.cloud.sentinel.datasource.ds2.nacos.data-type=json

spring.cloud.sentinel.datasource.ds2.nacos.rule-type=degrade



spring.cloud.sentinel.datasource.ds3.zk.path = /Sentinel-Demo/SYSTEM-CODE-DEMO-FLOW

spring.cloud.sentinel.datasource.ds3.zk.server-addr = localhost:2181

spring.cloud.sentinel.datasource.ds3.zk.rule-type=authority



spring.cloud.sentinel.datasource.ds4.apollo.namespace-name = application

spring.cloud.sentinel.datasource.ds4.apollo.flow-rules-key = sentinel

spring.cloud.sentinel.datasource.ds4.apollo.default-flow-rule-value = test

spring.cloud.sentinel.datasource.ds4.apollo.rule-type=param-flow

這種配置方式參考了 Spring Cloud Stream Binder 的配置,內部使用了 TreeMap 進行存儲,comparator  String.CASE_INSENSITIVE_ORDER 

Note

d1, ds2, ds3, ds4 是 ReadableDataSource 的名字,可隨意編寫。後面的 file zk nacos , apollo 就是對應具體的數據源,它們後面的配置就是這些具體數據源各自的配置。注意數據源的依賴要單獨引入(比如 sentinel-datasource-nacos)

每種數據源都有兩個共同的配置項: data-type converter-class 以及 rule-type

data-type 配置項表示 Converter 類型,Spring Cloud Alibaba Sentinel 默認提供兩種內置的值,分別是 json  xml (不填默認是json) 如果不想使用內置的 json  xml 這兩種 Converter,可以填寫 custom 表示自定義 Converter,然後再配置 converter-class 配置項,該配置項需要寫類的全路徑名(比如 spring.cloud.sentinel.datasource.ds1.file.converter-class=com.alibaba.cloud.examples.JsonFlowRuleListConverter)

rule-type 配置表示該數據源中的規則屬於哪種類型的規則(flowdegradeauthoritysystemparam-flowgw-flowgw-api-group)

Note

當某個數據源規則信息加載失敗的情況下,不會影響應用的啓動,會在日誌中打印出錯誤信息。

Note

默認情況下,xml 格式是不支持的。需要添加 jackson-dataformat-xml 依賴後纔會自動生效。

 

Note

如果規則加載沒有生效,有可能是 jdk 版本導致的,請關注 759 issue 的處理。

關於 Sentinel 動態數據源的實現原理,參考: 動態規則擴展

Zuul 支持

參考 Sentinel 網關限流文檔

若想跟 Sentinel Starter 配合使用,需要加上 spring-cloud-alibaba-sentinel-gateway 依賴,同時需要添加 spring-cloud-starter-netflix-zuul 依賴來讓 spring-cloud-alibaba-sentinel-gateway 模塊裏的 Zuul 自動化配置類生效:

<dependency>

    <groupId>com.alibaba.cloud</groupId>

    <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>

</dependency>



<dependency>

    <groupId>com.alibaba.cloud</groupId>

    <artifactId>spring-cloud-alibaba-sentinel-gateway</artifactId>

</dependency>



<dependency>

    <groupId>org.springframework.cloud</groupId>

    <artifactId>spring-cloud-starter-netflix-zuul</artifactId>

</dependency>

同時請將 spring.cloud.sentinel.filter.enabled 配置項置爲 false(若在網關流控控制檯上看到了 URL 資源,就是此配置項沒有置爲 false)。

Spring Cloud Gateway 支持

參考 Sentinel 網關限流文檔

若想跟 Sentinel Starter 配合使用,需要加上 spring-cloud-alibaba-sentinel-gateway 依賴,同時需要添加 spring-cloud-starter-gateway 依賴來讓 spring-cloud-alibaba-sentinel-gateway 模塊裏的 Spring Cloud Gateway 自動化配置類生效:

<dependency>

    <groupId>com.alibaba.cloud</groupId>

    <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>

</dependency>



<dependency>

    <groupId>com.alibaba.cloud</groupId>

    <artifactId>spring-cloud-alibaba-sentinel-gateway</artifactId>

</dependency>



<dependency>

    <groupId>org.springframework.cloud</groupId>

    <artifactId>spring-cloud-starter-gateway</artifactId>

</dependency>

同時請將 spring.cloud.sentinel.filter.enabled 配置項置爲 false(若在網關流控控制檯上看到了 URL 資源,就是此配置項沒有置爲 false)。

Endpoint 支持

在使用 Endpoint 特性之前需要在 Maven 中添加 spring-boot-starter-actuator 依賴,並在配置中允許 Endpoints 的訪問。

  • Spring Boot 1.x 中添加配置 management.security.enabled=false。暴露的 endpoint 路徑爲 /sentinel
  • Spring Boot 2.x 中添加配置 management.endpoints.web.exposure.include=*。暴露的 endpoint 路徑爲 /actuator/sentinel

Sentinel Endpoint 裏暴露的信息非常有用。包括當前應用的所有規則信息、日誌目錄、當前實例的 IPSentinel Dashboard 地址,Block Page,應用與 Sentinel Dashboard 的心跳頻率等等信息。

配置

下表顯示當應用的 ApplicationContext 中存在對應的Bean的類型時,會進行自動化設置:

存在Bean的類型

操作

作用

UrlCleaner

WebCallbackManager.setUrlCleaner(urlCleaner)

資源清理(資源(比如將滿足 /foo/:id 的 URL 都歸到 /foo/* 資源下))

UrlBlockHandler

WebCallbackManager.setUrlBlockHandler(urlBlockHandler)

自定義限流處理邏輯

RequestOriginParser

WebCallbackManager.setRequestOriginParser(requestOriginParser)

設置來源信息

Spring Cloud Alibaba Sentinel 提供了這些配置選項:

配置項

含義

默認值

spring.application.name or project.name

Sentinel項目名

 

spring.cloud.sentinel.enabled

Sentinel自動化配置是否生效

true

spring.cloud.sentinel.eager

是否提前觸發 Sentinel 初始化

false

spring.cloud.sentinel.transport.port

應用與Sentinel控制檯交互的端口,應用本地會起一個該端口占用的HttpServer

8719

spring.cloud.sentinel.transport.dashboard

Sentinel 控制檯地址

 

spring.cloud.sentinel.transport.heartbeat-interval-ms

應用與Sentinel控制檯的心跳間隔時間

 

spring.cloud.sentinel.transport.client-ip

此配置的客戶端IP將被註冊到 Sentinel Server 端

 

spring.cloud.sentinel.filter.order

Servlet Filter的加載順序。Starter內部會構造這個filter

Integer.MIN_VALUE

spring.cloud.sentinel.filter.url-patterns

數據類型是數組。表示Servlet Filter的url pattern集合

/*

spring.cloud.sentinel.filter.enabled

Enable to instance CommonFilter

true

spring.cloud.sentinel.metric.charset

metric文件字符集

UTF-8

spring.cloud.sentinel.metric.file-single-size

Sentinel metric 單個文件的大小

 

spring.cloud.sentinel.metric.file-total-count

Sentinel metric 總文件數量

 

spring.cloud.sentinel.log.dir

Sentinel 日誌文件所在的目錄

 

spring.cloud.sentinel.log.switch-pid

Sentinel 日誌文件名是否需要帶上 pid

false

spring.cloud.sentinel.servlet.block-page

自定義的跳轉 URL,當請求被限流時會自動跳轉至設定好的 URL

 

spring.cloud.sentinel.flow.cold-factor

WarmUp 模式中的 冷啓動因子

3

spring.cloud.sentinel.zuul.order.pre

SentinelZuulPreFilter 的 order

10000

spring.cloud.sentinel.zuul.order.post

SentinelZuulPostFilter 的 order

1000

spring.cloud.sentinel.zuul.order.error

SentinelZuulErrorFilter 的 order

-1

spring.cloud.sentinel.scg.fallback.mode

Spring Cloud Gateway 流控處理邏輯 (選擇 redirect or response)

 

spring.cloud.sentinel.scg.fallback.redirect

Spring Cloud Gateway 響應模式爲 'redirect' 模式對應的重定向 URL

 

spring.cloud.sentinel.scg.fallback.response-body

Spring Cloud Gateway 響應模式爲 'response' 模式對應的響應內容

 

spring.cloud.sentinel.scg.fallback.response-status

Spring Cloud Gateway 響應模式爲 'response' 模式對應的響應碼

429

spring.cloud.sentinel.scg.fallback.content-type

Spring Cloud Gateway 響應模式爲 'response' 模式對應的 content-type

application/json

 

Note

請注意。這些配置只有在 Servlet 環境下才會生效,RestTemplate 和 Feign 針對這些配置都無法生效

 

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