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的配置以及數據持久化;
詳細參看
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
的名字,可隨意編寫。後面的 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
配置表示該數據源中的規則屬於哪種類型的規則(flow
,degrade
,authority
,system
, param-flow
, gw-flow
, gw-api-group
)。
- 當某個數據源規則信息加載失敗的情況下,不會影響應用的啓動,會在日誌中打印出錯誤信息。
- 默認情況下,xml 格式是不支持的。需要添加
jackson-dataformat-xml
依賴後纔會自動生效。 - 如果規則加載沒有生效,有可能是 jdk 版本導致的,請關注 759 issue 的處理。
4、Push模式的演示,代碼整合演示
官方文檔用的zookeeper舉例,我這邊使用的nacos作爲註冊中心,就用nacos實現整合;
這個項目,是基於上一項目的基礎上,新增jar包以及yaml的配置,來完成的
4.1、在pom文件中,新增nacos-discovery
、Sentinel-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配置的對應的PropertiesConfiguration
的class
;
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