Sentinel數(shù)據(jù)源
Sentinel的數(shù)據(jù)源可以通過(guò)多種方式加載:json、xml文件取胎;zookeeper;apollo您市;nacos役衡;并且可以多種數(shù)據(jù)源同時(shí)使用榕莺。
擴(kuò)展方式
動(dòng)態(tài)數(shù)據(jù)源:DataSource`擴(kuò)展常見(jiàn)的實(shí)現(xiàn)方式
拉模式
客戶端主動(dòng)向某個(gè)規(guī)則管理中心定期輪詢拉取規(guī)則,這個(gè)規(guī)則中心可以是 RDBMS唠雕、文件及塘,甚至是 VCS 等。這樣做的方式是簡(jiǎn)單肋层,缺點(diǎn)是無(wú)法及時(shí)獲取變更栋猖;
推模式
規(guī)則中心統(tǒng)一推送,客戶端通過(guò)注冊(cè)監(jiān)聽(tīng)器的方式時(shí)刻監(jiān)聽(tīng)變化汪榔,比如使用 Nacos、Zookeeper 等配置中心雌团。這種方式有更好的實(shí)時(shí)性和一致性保證。
一:客戶端從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. 修改配置文件
默認(rèn)sentinel控制臺(tái)推送到nacos的dataId定義為: ${spring.application.name}-flow-rules
server.port=8083
# 配置中心url
spring.application.name=order-server
#注冊(cè)中心地址
spring.cloud.nacos.server-addr=192.168.64.128:8848
#添加sentinel依賴后 暴露/actuator/sentinel端點(diǎn)
# 開(kāi)啟健康檢查
management.endpoints.web.exposure.include=*
management.endpoint.health.show-details=ALWAYS
#打開(kāi)/關(guān)閉掉對(duì)Spring MVC端點(diǎn)的保護(hù)
spring.cloud.sentinel.filter.enabled=false
#這里的 spring.cloud.sentinel.transport.port 端口配置會(huì)在應(yīng)用對(duì)應(yīng)的機(jī)器上啟動(dòng)一個(gè) Http Server锦援,該 Server 會(huì)與 Sentinel 控制臺(tái)做交互。比如 Sentinel 控制臺(tái)添加了1個(gè)限流規(guī)則剥悟,會(huì)把規(guī)則數(shù)據(jù) push 給這個(gè) Http Server 接收灵寺,Http Server 再將規(guī)則注冊(cè)到 Sentinel 中。
spring.cloud.sentinel.transport.port=8731
#指定sentinel控制臺(tái)的地址
spring.cloud.sentinel.transport.dashboard=127.0.0.1:8080
# 設(shè)置Sentinel Nacos數(shù)據(jù)源配置略板;其中ds是數(shù)據(jù)源名叮称,可以自行隨意修改
# Nacos數(shù)據(jù)源地址(需要啟動(dòng)一臺(tái)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());
}
// 降級(jí)規(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是 應(yīng)用名-flow-rules
備注:
規(guī)則文件可以是json文件;也可以是text文件
規(guī)則是將 createOrder 的資源進(jìn)行限流 使用QPS 模式 限流閾值 1
[
{
"resource": "createOrder",
"limitApp": "default",
"grade": 1,
"count": 1,
"strategy": 0,
"controlBehavior": 0,
"clusterMode": false
}
]
5. 測(cè)試
訪問(wèn) http://localhost:8083/order/createorder/1 進(jìn)行測(cè)試
這樣會(huì)自動(dòng)從配置中心讀取配置信息不需要每次重啟都需要配置了
二:Sentinel控制臺(tái) 將熔斷規(guī)則推送到Nacos數(shù)據(jù)源悄窃。
控制臺(tái)改造主要是為規(guī)則實(shí)現(xiàn)
- DynamicRuleProvider:從Nacos上讀取配置
- DynamicRulePublisher:將規(guī)則推送到Nacos上
1.下載控制臺(tái)源碼
下載Sentinel控制臺(tái):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. 相關(guān)類修改
找到 sentinel-dashboard/src/test/java/com/alibaba/csp/sentinel/dashboard/rule/nacos目錄讥电,將整個(gè)目錄拷貝到 sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/rule/nacos
4.修改NacosConfig類
修改NacosConfig類,修改NacosIP地址
5. FlowControllerV1修改
自動(dòng)注入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);
}
測(cè)試
訪問(wèn)http://localhost:8080/可以進(jìn)入到控制臺(tái)界面恩敌,但是界面上沒(méi)有任何的客戶端
請(qǐng)求一次http://localhost:8083/order/createorder/1,等一會(huì)兒横媚,刷新一下就可以看到客戶端了
添加流控規(guī)則
并刷新一下就可以看到我們添加的規(guī)則了
在nacos配置中心查看
我們發(fā)現(xiàn)配置已經(jīng)被推送到了nacos
image.png
重啟客戶端進(jìn)行測(cè)試
重啟客戶端后發(fā)現(xiàn)我們的規(guī)則是生效的纠炮,并且修改規(guī)則后重啟客戶端規(guī)則也是生效的
訪問(wèn) http://localhost:8083/order/createorder/1 進(jìn)行測(cè)試