上篇文章大致讲解了sentinel的部署和一些基本概念以及使用,不清楚的同学建议先学习前一篇文章
传送门:https://blog.youkuaiyun.com/qq_22624361/article/details/90258222
这篇文章主要讲解sentinel与配置中心多数据源的结合。
需要结合数据源的原因是因为sentinel默认的数据是储存在内存里的,并没有实现持久化的工程,使用过程中规则数据的丢失会引起我们的使用不便。
持久化的方法主要有两种,一种是数据化直接储存,另一种是通过与配置中心的交互来更新和储存数据。
前一种方法需要自己重写实现接口,这里就不尝试了,需要尝试的同学可以参考其他大佬的文章。
传送门:https://www.cnblogs.com/cdfive2018/p/9838577.html
因为早期部署了携程开源的apollo,所以我们这里就拿apollo来实现,后期会出关于约nacos config整合的文章。
我们可以看下关于整合多数据源的官方文档
https://github.com/alibaba/Sentinel/wiki/在生产环境中使用-Sentinel
主要有三种模式,那么这里我们主要也是用官方所推荐的push模式。
关于push模式的流程图我们借用程序员DD大神的图来给大家呈现一下
开启pus模式主要分两块,第一块是对sentinel控制面板的改造;第二块是客户端的改造。
我们先来说关于sentinel-dashboard的改造。改造的原因主要是实现两点:
1.sentinel界面显示我们在配置中心发布的规则。
2.sentinel修改规则后可以同步推送到配置中心
第一步,我们先从官方git库把源码给拉下来,然后根据官方文档来进行改造
https://github.com/alibaba/Sentinel/wiki/Sentinel-控制台(集群流控管理)#规则配置
我们
我们可以看到官方已经给出了demo,然后我们进行改造。
第二步,首先我们在java包下面的com.alibaba.csp.sentinel.dashboard.rule创建一个apollo包,然后创建三个类ApolloConfig,FlowRuleApolloProvider,FlowRuleApolloPublisher
然后我们来改造ApolloConfig
@Configuration
public class ApolloConfig {
@Bean
public Converter<List<FlowRuleEntity>, String> flowRuleEntityEncoder() {
return JSON::toJSONString;
}
@Bean
public Converter<String, List<FlowRuleEntity>> flowRuleEntityDecoder() {
return s -> JSON.parseArray(s, FlowRuleEntity.class);
}
@Bean
public ApolloOpenApiClient apolloOpenApiClient() {
ApolloOpenApiClient client = ApolloOpenApiClient.newBuilder()
.withPortalUrl("http://localhost:10034") // TODO 根据实际情况修改(portal_address)
.withToken("token") // TODO apollo开发api的token
.build();
return client;
}
}
.withPortalUrl里面配置的是apollo的portal服务的地址,这里如果填错是会报openAPI 404;
.withToken 里面配置的apollo的openAPI的token;
如果不了解怎么配置openAPI的同学可以参考这篇文章
https://www.jianshu.com/p/6e243bfa9ed2
至此,ApolloConfig配置结束。
第三步,改造FlowRuleApolloProvider和FlowRuleApolloPublisher
这里的两类主要是负责sentinel向配置中心推送规则以及向配置中心拉取已经发布的规则。
先来看FlowRuleApolloProvider:
@Component("flowRuleApolloProvider")
public class FlowRuleApolloProvider implements DynamicRuleProvider<List<FlowRuleEntity>> {
@Autowired
private ApolloOpenApiClient apolloOpenApiClient;
@Autowired
private Converter<String, List<FlowRuleEntity>> converter;
@Value("${env:DEV}")
private String env;
@Override
public List<FlowRuleEntity> getRules(String appName) throws Exception {
String appId = "sentinel-server";
// flowDataId对应
String flowDataId = "sentinel.flowRules";
OpenNamespaceDTO openNamespaceDTO = apolloOpenApiClient.getNamespace(appId, env, null, "application");
String rules = openNamespaceDTO
.getItems()
.stream()
.filter(p -> p.getKey().equals(flowDataId))
.map(OpenItemDTO::getValue)
.findFirst()
.orElse("");
if (StringUtil.isEmpty(rules)) {
return new ArrayList<>();
}
return converter.convert(rules);
}
我们主要来看这两行代码:
appId:这里的appId就是你在apollo里面设置的appId,如果不设置会取你在客户端配置的appName.
env:部署的环境。
clusterName:集群部署名称,如没有集群则填写"default"
namespaceName:apollo中设置的namespaceName
flowDataId:这个就是你在apollo中设置的规则keyname
然后设置FlowRuleApolloPublisher
@Component("flowRuleApolloPublisher")
public class FlowRuleApolloPublisher implements DynamicRulePublisher<List<FlowRuleEntity>> {
@Autowired
private ApolloOpenApiClient apolloOpenApiClient;
@Autowired
private Converter<List<FlowRuleEntity>, String> converter;
@Value("${env:DEV}")
private String env;
@Override
public void publish(String app, List<FlowRuleEntity> rules) throws Exception {
if (rules == null) {
return;
}
// Increase the configuration
String appId = "sentinel-server";
String flowDataId = "sentinel.flowRules";
OpenItemDTO openItemDTO = new OpenItemDTO();
openItemDTO.setKey(flowDataId);
openItemDTO.setValue(converter.convert(rules));
openItemDTO.setComment("Program auto-join");
openItemDTO.setDataChangeCreatedBy("apollo");
apolloOpenApiClient.createOrUpdateItem(appId, "DEV", "sentinel-server", "application", openItemDTO);
// Release configuration
NamespaceReleaseDTO namespaceReleaseDTO = new NamespaceReleaseDTO();
namespaceReleaseDTO.setEmergencyPublish(true);
namespaceReleaseDTO.setReleaseComment("Modify or add configurations");
namespaceReleaseDTO.setReleasedBy("apollo");
namespaceReleaseDTO.setReleaseTitle("Modify or add configurations");
apolloOpenApiClient.publishNamespace(appId, "DEV", "sentinel-server", "application", namespaceReleaseDTO);
}
这里的参数基本上与上面的provider保持一致,但是我们这里要设置数据创建者
第四步,修改pom文件,将test注释掉
<dependency>
<groupId>com.ctrip.framework.apollo</groupId>
<artifactId>apollo-openapi</artifactId>
<version>1.2.0</version>
<!--<scope>test</scope>-->
</dependency>
第五步,修改resources/app/scripts/directives/sidebar/sidebar.html文件
将
<li ui-sref-active="active">
<a ui-sref="dashboard.flowV1({app: entry.app})">
<i class="glyphicon glyphicon-filter"></i> 流控规则
</a>
</li>
修改为
<li ui-sref-active="active">
<a ui-sref="dashboard.flow({app: entry.app})">
<i class="glyphicon glyphicon-filter"></i> 流控规则
</a>
</li>
第六步,修改com.alibaba.csp.sentinel.dashboard.controller.v2.FlowControllerV2,将刚才我们修改的provide和publisher注入
@Autowired
@Qualifier("flowRuleApolloProvider")
private DynamicRuleProvider<List<FlowRuleEntity>> ruleProvider;
@Autowired
@Qualifier("flowRuleApolloPublisher")
private DynamicRulePublisher<List<FlowRuleEntity>> rulePublisher;
至此我们对于sentinel的dashboard的改造就完成了。
接下来的一大部分是对客户端的改造
第一步,引入依赖
<!--alibaba sentinel dataSource pull-->
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-extension</artifactId>
<version>${sentinel.version}</version>
</dependency>
<!--流控储存在apollo-->
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-apollo</artifactId>
<version>${sentinel.version}</version>
</dependency>
第二步,配置关于apollo配置中心的信息
#apollo配置中心设置
app.id=test-server
apollo.meta=http://localhost:8080
#sentinel配置
spring.cloud.sentinel.transport.port=8081
spring.cloud.sentinel.transport.dashboard=localhost:8080
# sentinel datasource apollo
#apollo的nameSpace
spring.cloud.sentinel.datasource.ds1.apollo.namespaceName=application
##流控规则
##规则类型
spring.cloud.sentinel.datasource.ds1.apollo.rule-type=flow
##配置中心里面的key
spring.cloud.sentinel.datasource.ds1.apollo.flowRulesKey=sentinel.flowRules
参数解释:
spring.cloud.sentinel.datasource.ds1:sentinel中命名的多数据源配置规则,后面可以跟ds1,ds2…等等来适配多种数据源。
apollo.rule-type:规则类型 flow代表了限流。
我们可以看到里面还有其他规则类型。
**apollo.flowRulesKey:**配置中心里面的key。这里的key和配置中心的key已经控制面板里面改造的flowDataId都是得保持一致的。这样数据才会互通。
这样,客户端也改造完成了。
我们依次启动apollo配置中心,sentinel控制台,客户端来看下效果。
我们在apollo先设置一个规则
这里需要注意的是规则按json方式进行交互,如果想添加第二条流控规则,则添加json对象在数组里面即可。
然后我们请求接口之后来看控制台
规则也在控制台显示。
那么我们再来试一下推送模式,我们在sentinel修改规则
然后来看配置中心
配置中心也同步更新。
项目地址:
https://github.com/fjc440/spring-cloud-learn/tree/feature-apollo