一個名叫Sentinel-Rules-SDK的元件,使得Sentinel的流控&熔斷規則的配置更加方便

不送花的程式猿發表於2021-03-15

原文連結:一個名叫Sentinel-Rules-SDK的元件,使得Sentinel的流控&熔斷規則的配置更加方便

1 Sentinel 是什麼?

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

2 Sentinel 具有以下特徵:

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

好了,其他的就不多做介紹了,大家可以看官網:https://github.com/alibaba/Sentinel/wiki/介紹

3 如何接入 Sentinel

之前我寫過一篇文章講Dubbo如何引入Sentinel做熔斷限流,而其中為資源配置限流規則和熔斷規則有兩種方式:

  • 硬程式碼初始化:我們可以利用 static 靜態程式碼塊來初始化,但是如果專案每次要為資源修改規則,就要修改專案程式碼,然後重新打包部署
  • 利用控制檯來配置:因為硬程式碼的不方便,所以一般我們會利用控制檯來為資源配置流控和熔斷規則。這個只能在專案啟動後獲取到所有資源,然後一個一個配置,但是這時候如果大流量打過來,就很容易導致系統崩潰。

所以暫時最好的實踐就是:硬程式碼+控制檯

在專案啟動時,可以利用硬程式碼先將資源初始化好,接著控制檯可以隨時調整根據線上的執行情況調整規則。

4 Sentinel-Rules-SDK

但是,在我看來,我還是比較喜歡將初始化規則維護在配置檔案中,由配置中心統一管理Sentinel的流控規則和熔斷規則。

因為有了上面的實踐和思考,所以自己研發了一款簡單易用的元件,將資源的流控&熔斷規則放在配置檔案中。

  • 在專案啟動時,SDK會讀取配置檔案中的配置,然後進行 Sentinel 規則的初始化;
  • 如果團隊還用了 Sentinel 提供的控制檯,當帶 Sentinel 規則的介面被呼叫時,就會將所有的限流規則和熔斷規則上傳到 Sentinel 控制檯中;
  • 接下來,我們可以在控制檯上看實時監控反饋的情況,根據需要來調整流控規則和熔斷規則,控制檯調整後的規則會同步到專案的記憶體中。

4.1 使用介紹

引入依賴:

<dependency>
    <groupId>com.github.howinfun</groupId>
    <artifactId>sentinel-rules-sdk</artifactId>
    <version>1.0.0-SNAPSHOT</version>
</dependency>

自己在本地拉程式碼,然後deploy,最後引入依賴

規則配置:

屬性基本和Sentinel 提供的 FlowRule 和 DegradeRule 一一對應上,滿足基本功能點。
詳情看下面例子:

# 開啟元件功能
sentinel.rules.enabled=true
# 流控&熔斷規則配置
sentinel.rules.flowRuleList[0].resource=sayHello
sentinel.rules.flowRuleList[0].grade=1
sentinel.rules.flowRuleList[0].count=1

sentinel.rules.degradeRuleList[0].resource=sayHello
sentinel.rules.degradeRuleList[0].grade=2
sentinel.rules.degradeRuleList[0].count=1
sentinel.rules.degradeRuleList[0].timeWindow=1
sentinel.rules.degradeRuleList[0].minRequestAmount=1
sentinel.rules.degradeRuleList[0].statIntervalMs=10000

sentinel.rules.flowRuleList[1].resource=sayHi
sentinel.rules.flowRuleList[1].grade=1
sentinel.rules.flowRuleList[1].count=1

sentinel.rules.degradeRuleList[1].resource=sayHi
sentinel.rules.degradeRuleList[1].grade=2
sentinel.rules.degradeRuleList[1].count=1
sentinel.rules.degradeRuleList[1].timeWindow=1
sentinel.rules.degradeRuleList[1].minRequestAmount=1
sentinel.rules.degradeRuleList[1].statIntervalMs=10000

使用介紹已經結束,就是這麼簡單,畢竟原理其實就是拿到配置的內容,然後進行初始化。下面看看功能是如何實現的。

4.2 實現介紹

核心類有兩個:SentinelRulesProperties 和 SentinelRulesGenerateConfig

看名稱我們就知道這兩個類的功能點了。第一個是屬性類,負責讀取配置檔案中的規則。第二個是配置類,負責初始化流控規則和熔斷規則。

SentinelRulesProperties:

SentinelRulesProperties 非常簡單,只是利用 @ConfigurationProperties 註解來完成配置規則的注入。
當然了,我們要記得找個地方利用 @EnableConfigurationProperties 將這個屬性類加上,不然讀取不了配置檔案中的規則內容。

/**
 * Sentinel規則配置
 * @author winfun
 * @date 2021/3/4 4:26 下午
 **/
@Data
@ConfigurationProperties(prefix = "sentinel.rules")
public class SentinelRulesProperties {

    private Boolean enabled;
    private List<SentinelFlowRule> flowRuleList;
    private List<SentinelDegradeRule> degradeRuleList;
}

SentinelRulesGenerateConfig:

SentinelRulesGenerateConfig 配置類也很簡單,主要是利用 Spring 提供的監聽器,監聽ContextRefreshedEvent事件,即Spring容器初始化完畢,接著利用 ApplicationContext 來獲取上面的屬性類,然後讀取流控規則和熔斷規則,最後進行初始化。

/**
 * Sentinel規則自動生成配置類
 * @author winfun
 * @date 2021/3/4 4:29 下午
 **/
@Configuration
@ConditionalOnProperty(prefix = "sentinel.rules", name = "enabled", havingValue = "true")
@EnableConfigurationProperties({SentinelRulesProperties.class})
public class SentinelRulesGenerateConfig implements ApplicationListener<ContextRefreshedEvent>, ApplicationContextAware {

    private ApplicationContext applicationContext;

    @Override
    public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) {
        SentinelRulesProperties sentinelRulesProperties =
                this.applicationContext.getBean(SentinelRulesProperties.class);
        List<SentinelFlowRule> flowRuleList = sentinelRulesProperties.getFlowRuleList();
        List<SentinelDegradeRule> degradeRuleList = sentinelRulesProperties.getDegradeRuleList();

        final List<FlowRule> flowRules = new ArrayList<>();
        final List<DegradeRule> degradeRules = new ArrayList<>();
        // 處理流控規則
        flowRuleList.forEach(sentinelFlowRule -> {
            FlowRule flowRule = new FlowRule();
            BeanUtils.copyProperties(sentinelFlowRule,flowRule);
            flowRules.add(flowRule);
        });
        // 處理熔斷規則
        degradeRuleList.forEach(sentinelDegradeRule -> {
            DegradeRule degradeRule = new DegradeRule();
            BeanUtils.copyProperties(sentinelDegradeRule,degradeRule);
            degradeRules.add(degradeRule);
        });
        FlowRuleManager.loadRules(flowRules);
        DegradeRuleManager.loadRules(degradeRules);
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }
}

如果大家對這個元件還感興趣的話,可以到Github上看看:https://github.com/Howinfun/study-in-work-and-life/tree/master/sentinel-rules-sdk

相關文章