spring-cloud-alibaba.2.2.x Sentinel整合nacos持久化

spring-cloud-alibaba.2.2.x Sentinel整合nacos持久化


本地項目的基礎環境

環境 版本
jdk 1.8.0_201
maven 3.6.0
Spring-boot 2.2.4.RELEASE
Spring-cloud-alibaba 2.2.1.RELEASE
Spring-cloud Hoxton.SR2
nacos 1.2.1
sentinel-dashboard 1.7.1

構建本項目之前,請詳細參看如下步驟,如果已經搭建好,略過即可;

項目地址的碼雲的git地址https://gitee.com/liqi01/badger-spring-cloud-alibaba.git

《spring-cloud-alibaba.2.2.x 服務註冊與發現nacos簡介以及環境搭建》

《spring-cloud-alibaba2.2.x 遠程調用負載均衡ribbon搭建使用》

《spring-cloud-alibaba2.2.x 遠程調用負載均衡openfeign搭建使用》

《spring-cloud-alibaba.2.2.x Sentinel分佈式系統的流量防衛兵的簡介以及環境搭建》

《spring-cloud-alibaba.2.2.x Sentinel持久化整合nacos,nacos無法獲取配置信息bug解決》

在官方文檔在生產環境中使用-Sentinel這個章節裏,有詳細介紹生產環境中,sentinel的配置以及數據持久化;

詳細參看

https://github.com/alibaba/Sentinel/wiki/%E5%9C%A8%E7%94%9F%E4%BA%A7%E7%8E%AF%E5%A2%83%E4%B8%AD%E4%BD%BF%E7%94%A8-Sentinel

1、生產環境的 Sentinel Dashboard 需要具備下面幾個特性:

  • 規則管理及推送,集中管理和推送規則。sentinel-core 提供 API 和擴展接口來接收信息。開發者需要根據自己的環境,選取一個可靠的推送規則方式;同時,規則最好在控制檯中集中管理。
  • 監控,支持可靠、快速的實時監控和歷史監控數據查詢。sentinel-core 記錄秒級的資源運行情況,並且提供 API 來拉取資源運行信息。當機器大於一臺以上的時候,可以通過 Dashboard 來拉取,聚合,並且存儲這些信息。這個時候,Dashboard 需要有一個存儲媒介,來存儲歷史運行情況。
  • 權限控制,區分用戶角色,來進行操作。生產環境下的權限控制是非常重要的,理論上只有管理員等高級用戶纔有權限去修改應用的規則。

由於開發者有各自不一樣的環境和需求,我們會對“規則管理和推送”,“監控”這兩個方面給出建議以及最佳實踐;對於權限控制,由於每個開發者的環境都不一樣,我們在最佳實踐中僅僅使用了簡單的認證。開發者可以依循自己的需求,結合實際生產環境,選擇最適合自己的方式。

2、規則管理及推送

一般來說,規則的推送有下面三種模式:

推送模式 說明 優點 缺點
原始模式 API 將規則推送至客戶端並直接更新到內存中,擴展寫數據源(WritableDataSource 簡單,無任何依賴 不保證一致性;規則保存在內存中,重啓即消失。嚴重不建議用於生產環境
Pull 模式 擴展寫數據源(WritableDataSource), 客戶端主動向某個規則管理中心定期輪詢拉取規則,這個規則中心可以是 RDBMS、文件 等 簡單,無任何依賴;規則持久化 不保證一致性;實時性不保證,拉取過於頻繁也可能會有性能問題。
Push 模式 擴展讀數據源(ReadableDataSource),規則中心統一推送,客戶端通過註冊監聽器的方式時刻監聽變化,比如使用 Nacos、Zookeeper 等配置中心。這種方式有更好的實時性和一致性保證。生產環境下一般採用 push 模式的數據源。 規則持久化;一致性;快速 引入第三方依賴

2.1、原始模式

如果不做任何修改,Dashboard 的推送規則方式是通過 API 將規則推送至客戶端並直接更新到內存中;

這種做法的好處是簡單,無依賴;壞處是應用重啓規則就會消失,僅用於簡單測試,不能用於生產環境。

2.2、Pull模式

pull 模式的數據源(如本地文件、RDBMS 等)一般是可寫入的。使用時需要在客戶端註冊數據源:將對應的讀數據源註冊至對應的 RuleManager,將寫數據源註冊至 transport 的 WritableDataSourceRegistry 中。以本地文件數據源爲例:

public class FileDataSourceInit implements InitFunc {

    @Override
    public void init() throws Exception {
        String flowRulePath = "xxx";

        ReadableDataSource<String, List<FlowRule>> ds = new FileRefreshableDataSource<>(
            flowRulePath, source -> JSON.parseObject(source, new TypeReference<List<FlowRule>>() {})
        );
        // 將可讀數據源註冊至 FlowRuleManager.
        FlowRuleManager.register2Property(ds.getProperty());

        WritableDataSource<List<FlowRule>> wds = new FileWritableDataSource<>(flowRulePath, this::encodeJson);
        // 將可寫數據源註冊至 transport 模塊的 WritableDataSourceRegistry 中.
        // 這樣收到控制檯推送的規則時,Sentinel 會先更新到內存,然後將規則寫入到文件中.
        WritableDataSourceRegistry.registerFlowDataSource(wds);
    }

    private <T> String encodeJson(T t) {
        return JSON.toJSONString(t);
    }
}

本地文件數據源會定時輪詢文件的變更,讀取規則。這樣我們既可以在應用本地直接修改文件來更新規則,也可以通過 Sentinel 控制檯推送規則。以本地文件數據源爲例,推送過程如下圖所示:

首先 Sentinel 控制檯通過 API 將規則推送至客戶端並更新到內存中,接着註冊的寫數據源會將新的規則保存到本地的文件中。使用 pull 模式的數據源時一般不需要對 Sentinel 控制檯進行改造。

這種實現方法好處是簡單,不引入新的依賴,壞處是無法保證監控數據的一致性。

2.3、Push模式

生產環境下一般更常用的是 push 模式的數據源。對於 push 模式的數據源,如遠程配置中心(ZooKeeper, Nacos, Apollo等等),推送的操作不應由 Sentinel 客戶端進行,而應該經控制檯統一進行管理,直接進行推送,數據源僅負責獲取配置中心推送的配置並更新到本地。因此推送規則正確做法應該是 配置中心控制檯/Sentinel 控制檯 → 配置中心 → Sentinel 數據源 → Sentinel,而不是經 Sentinel 數據源推送至配置中心。這樣的流程就非常清晰了:

3、動態數據源支持

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

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

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

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

rule-type 配置表示該數據源中的規則屬於哪種類型的規則(flowdegradeauthoritysystem, param-flow, gw-flow, gw-api-group)。

  1. 當某個數據源規則信息加載失敗的情況下,不會影響應用的啓動,會在日誌中打印出錯誤信息。
  2. 默認情況下,xml 格式是不支持的。需要添加 jackson-dataformat-xml 依賴後纔會自動生效。
  3. 如果規則加載沒有生效,有可能是 jdk 版本導致的,請關注 759 issue 的處理。

4、Push模式的演示,代碼整合演示

官方文檔用的zookeeper舉例,我這邊使用的nacos作爲註冊中心,就用nacos實現整合;

這個項目,是基於上一項目的基礎上,新增jar包以及yaml的配置,來完成的

4.1、在pom文件中,新增nacos-discoverySentinel-datasource-nacos

完整文件如下

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.4.RELEASE</version>
    </parent>
    <groupId>com.badger</groupId>
    <artifactId>badger-spring-cloud-alibaba-sentinel</artifactId>
    <name>badger-spring-cloud-alibaba-sentinel</name>
    <description>服務熔斷、限流</description>
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <java.version>1.8</java.version>
        <maven-jar-plugin.version>3.1.1</maven-jar-plugin.version>
        <nacos.version>1.2.1</nacos.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba.csp</groupId>
            <artifactId>sentinel-datasource-nacos</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>com.alibaba.nacos</groupId>
                    <artifactId>nacos-client</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
        </dependency>
    </dependencies>
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>2.2.1.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
    <build>
        <plugins>
            <!-- 打包插件 -->
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
        <finalName>badger-spring-cloud-alibaba-sentinel</finalName>
    </build>
</project>

4.2、yaml文件中,新增nacos註冊中心配置

完整文件如下

server:
  port: 9000
spring:
  application:
    name: badger-spring-cloud-alibaba-sentinel
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848
    sentinel:
      transport:
        dashboard: 127.0.0.1:8080
        port: 8719
      datasource:
        ds1:
          nacos:
            server-addr: 127.0.0.1:8848
            data-id: ${spring.application.name}
            rule-type: flow
management:
  endpoints:
    web:
      exposure:
        include: '*'

更詳細的配置,可以參看對應的yml配置的對應的PropertiesConfigurationclass;

com.alibaba.cloud.sentinel.datasource.config.DataSourcePropertiesConfiguration.class

4.3、業務代碼中,新增服務註冊和發現的註解@EnableDiscoveryClient

完整文件如下

/**
 * @EnableDiscoveryClient 開啓服務註冊和發現
 */
@SpringBootApplication
@EnableDiscoveryClient
public class SentinelApplication {

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

    @RestController
    public class DemoController {

        @GetMapping(value = "/hello/{name}")
        @SentinelResource(value = "sayHello")
        public String apiHello(@PathVariable String name) {
            return "Hello, " + name;
        }

        @GetMapping("/demo")
        public String test() {
            return "demo";
        }
    }
}

5、測試

5.1、啓動對應的應用

1、啓動nacos

./startup.sh -m standalone

2、啓動sentinel-dashboard-1.7.1

nohup java -jar sentinel-dashboard-1.7.1.jar >/dev/null 2>&1 &

3、啓動應用badger-spring-cloud-alibaba-sentinel

4、在nacos中,新增流控規則的配置

dataId:爲yml文件中配置的

group:默認爲DEFAULT_GROUP,也可以在yml文件中指定

在nacos中,需要三個座標來確認唯一的配置文件(命名空間(默認爲public)、group、dataId)

[
	{
		"resource":"/demo",
		"limitApp":"default",
		"grade":1,
		"count":1,
		"strategy":0,
		"controlBehavior":0,
		"clusterMode":"false"
	}
]

5、執行接口調用http://localhost:9000/demo

多次刷新

結果:Blocked by Sentinel (flow limiting)

在sentinel的控制檯,也從nacos中,拿到了對應的流控規則;

6、配置的json說明

[
	{
		"resource":"/demo",
		"limitApp":"default",
		"grade":1,
		"count":1,
		"strategy":0,
		"controlBehavior":0,
		"clusterMode":"false"
	}
]

resource:資源名稱;

limitApp:來源應用(默認)

grade:閾值類型;0:線程數;1:表示QPS

strategy:流控模式,0:直接;1:關聯;2:鏈路

controlBehavior:流控的結果;0:快速失敗;1:Warm up;2:排隊等待

clusterMode:是否集羣。

github官方文檔;

https://github.com/alibaba/spring-cloud-alibaba/wiki/Sentinel

https://github.com/alibaba/Sentinel/wiki/%E4%BB%8B%E7%BB%8D

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