Sentinel數(shù)據(jù)源
Sentinel的數(shù)據(jù)源可以通過多種方式加載:json、xml文件;zookeeper;apollo;nacos;并且可以多種數(shù)據(jù)源同時使用。
擴展方式
動態(tài)數(shù)據(jù)源:DataSource`擴展常見的實現(xiàn)方式
拉模式
客戶端主動向某個規(guī)則管理中心定期輪詢拉取規(guī)則,這個規(guī)則中心可以是 RDBMS、文件,甚至是 VCS 等。這樣做的方式是簡單,缺點是無法及時獲取變更;
推模式
規(guī)則中心統(tǒng)一推送,客戶端通過注冊監(jiān)聽器的方式時刻監(jiān)聽變化,比如使用 Nacos、Zookeeper 等配置中心。這種方式有更好的實時性和一致性保證。
一:客戶端從Nacos讀取限流規(guī)則
Sentinel客戶端配置
1. 引入POM依賴
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
<version>2.2.1.RELEASE</version>
</dependency>
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-nacos</artifactId>
<version>1.7.2</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.70</version>
</dependency>
2. 修改配置文件
默認sentinel控制臺推送到nacos的dataId定義為: ${spring.application.name}-flow-rules
server.port=8083
# 配置中心url
spring.application.name=order-server
#注冊中心地址
spring.cloud.nacos.server-addr=192.168.64.128:8848
#添加sentinel依賴后 暴露/actuator/sentinel端點
# 開啟健康檢查
management.endpoints.web.exposure.include=*
management.endpoint.health.show-details=ALWAYS
#打開/關閉掉對Spring MVC端點的保護
spring.cloud.sentinel.filter.enabled=false
#這里的 spring.cloud.sentinel.transport.port 端口配置會在應用對應的機器上啟動一個 Http Server,該 Server 會與 Sentinel 控制臺做交互。比如 Sentinel 控制臺添加了1個限流規(guī)則,會把規(guī)則數(shù)據(jù) push 給這個 Http Server 接收,Http Server 再將規(guī)則注冊到 Sentinel 中。
spring.cloud.sentinel.transport.port=8731
#指定sentinel控制臺的地址
spring.cloud.sentinel.transport.dashboard=127.0.0.1:8080
# 設置Sentinel Nacos數(shù)據(jù)源配置;其中ds是數(shù)據(jù)源名,可以自行隨意修改
# Nacos數(shù)據(jù)源地址(需要啟動一臺Nacos Server)
# nacos 地址
spring.cloud.sentinel.datasource.ds.nacos.server-addr=${spring.cloud.nacos.server-addr}
spring.cloud.sentinel.datasource.ds.nacos.dataId=${spring.application.name}-flow-rules
spring.cloud.sentinel.datasource.ds.nacos.groupId=SENTINEL_GROUP
# 數(shù)據(jù)類型
spring.cloud.sentinel.datasource.ds3.nacos.data-type=json
# 規(guī)則類型
spring.cloud.sentinel.datasource.ds.nacos.rule-type=flow
3. 添加Nacos數(shù)據(jù)源配置類
@Configuration
public class DataSourceInitFunc {
Logger logger = LoggerFactory.getLogger(DataSourceInitFunc.class);
@Autowired
private SentinelProperties sentinelProperties;
@Bean
public DataSourceInitFunc init() throws Exception {
logger.info("[NacosSource初始化,從Nacos中獲取熔斷規(guī)則]");
sentinelProperties.getDatasource().entrySet().stream().filter(map -> {
return map.getValue().getNacos() != null;
}).forEach(map -> {
NacosDataSourceProperties nacos = map.getValue().getNacos();
// 限流規(guī)則,需要Nacos的dataId中包含flow字符串
if (nacos.getDataId().contains("flow")) {
ReadableDataSource<String, List<FlowRule>> flowRuleDataSource = new NacosDataSource<>(nacos.getServerAddr(),
nacos.getGroupId(), nacos.getDataId(),
source -> JSON.parseObject(source, new TypeReference<List<FlowRule>>() {
}));
FlowRuleManager.register2Property(flowRuleDataSource.getProperty());
}
// 降級規(guī)則,需要Nacos的dataId中包含degrade字符串
if (nacos.getDataId().contains("degrade")) {
ReadableDataSource<String, List<DegradeRule>> degradeRuleDataSource = new NacosDataSource<>(nacos.getServerAddr(),
nacos.getGroupId(), nacos.getDataId(),
source -> JSON.parseObject(source, new TypeReference<List<DegradeRule>>() {
}));
DegradeRuleManager.register2Property(degradeRuleDataSource.getProperty());
}
});
return new DataSourceInitFunc();
}
}
4. Nacos中添加熔斷規(guī)則
根據(jù)配置文件配置的 id是 應用名-flow-rules

備注:
規(guī)則文件可以是json文件;也可以是text文件
規(guī)則是將 createOrder 的資源進行限流 使用QPS 模式 限流閾值 1
[
{
"resource": "createOrder",
"limitApp": "default",
"grade": 1,
"count": 1,
"strategy": 0,
"controlBehavior": 0,
"clusterMode": false
}
]
5. 測試
訪問 http://localhost:8083/order/createorder/1 進行測試

這樣會自動從配置中心讀取配置信息不需要每次重啟都需要配置了
二:Sentinel控制臺 將熔斷規(guī)則推送到Nacos數(shù)據(jù)源。
控制臺改造主要是為規(guī)則實現(xiàn)
- DynamicRuleProvider:從Nacos上讀取配置
- DynamicRulePublisher:將規(guī)則推送到Nacos上
1.下載控制臺源碼
下載Sentinel控制臺:https://github.com/alibaba/Sentinel/releases

2.修改POM文件
將sentinel-datasource-nacos的 <scope>test</scope> 這一行注釋掉
<!-- for Nacos rule publisher sample -->
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-nacos</artifactId>
<!-- <scope>test</scope>-->
</dependency>
3. 相關類修改
找到 sentinel-dashboard/src/test/java/com/alibaba/csp/sentinel/dashboard/rule/nacos目錄,將整個目錄拷貝到 sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/rule/nacos

4.修改NacosConfig類
修改NacosConfig類,修改NacosIP地址

5. FlowControllerV1修改
自動注入provider和publisher
@Autowired
@Qualifier("flowRuleNacosProvider")
private DynamicRuleProvider<List<FlowRuleEntity>> ruleProvider;
@Autowired
@Qualifier("flowRuleNacosPublisher")
private DynamicRulePublisher<List<FlowRuleEntity>> rulePublisher;

修改rules接口,讀取nacos中的數(shù)據(jù)
@GetMapping("/rules")
@AuthAction(PrivilegeType.READ_RULE)
public Result<List<FlowRuleEntity>> apiQueryMachineRules(@RequestParam String app) {
if (StringUtil.isEmpty(app)) {
return Result.ofFail(-1, "app can't be null or empty");
}
try {
List<FlowRuleEntity> rules = ruleProvider.getRules(app);
if (rules != null && !rules.isEmpty()) {
for (FlowRuleEntity entity : rules) {
entity.setApp(app);
if (entity.getClusterConfig() != null && entity.getClusterConfig().getFlowId() != null) {
entity.setId(entity.getClusterConfig().getFlowId());
}
}
}
rules = repository.saveAll(rules);
return Result.ofSuccess(rules);
} catch (Throwable throwable) {
logger.error("Error when querying flow rules", throwable);
return Result.ofThrowable(-1, throwable);
}
}

該類最后的publishRules方法修改如下
private CompletableFuture<Void> publishRules(String app, String ip, Integer port) {
List<FlowRuleEntity> rules = repository.findAllByMachine(MachineInfo.of(app, ip, port));
try {
rulePublisher.publish(app, rules);
logger.info("添加限流規(guī)則成功.....");
} catch (Exception e) {
e.printStackTrace();
logger.info("添加限流規(guī)則失敗.....");
}
return sentinelApiClient.setFlowRuleOfMachineAsync(app, ip, port, rules);
}

測試
訪問http://localhost:8080/可以進入到控制臺界面,但是界面上沒有任何的客戶端
請求一次http://localhost:8083/order/createorder/1,等一會兒,刷新一下就可以看到客戶端了

添加流控規(guī)則

并刷新一下就可以看到我們添加的規(guī)則了

在nacos配置中心查看
我們發(fā)現(xiàn)配置已經(jīng)被推送到了nacos
image.png
重啟客戶端進行測試
重啟客戶端后發(fā)現(xiàn)我們的規(guī)則是生效的,并且修改規(guī)則后重啟客戶端規(guī)則也是生效的

