点击蓝色“程序猿DD”关注我哟

加个“星标”,不忘签到哦


在之前的两篇教程中我们分别介绍了如何将Sentinel的限流规则存储到Nacos和Apollo中。同时,在文末的思考中,我都指出了这两套整合方案都存在一个不足之处:不论采用什么配置中心,限流规则都只能通过Nacos界面或Apollo界面来完成修改才能得到持久化存储,而在Sentinel Dashboard中修改限流规则虽然可以生效,但是不会被持久化到配置中心。而在这两个配置中心里存储的数据是一个Json格式,当存储的规则越来越多,对该Json配置的可读性与可维护性会变的越来越差。所以,下面我们就来继续探讨这个不足之处,并给出相应的解决方案。本文以Apollo存储为例,下一篇介绍Nacos的改在示例。

问题分析

在实际操作之前,我们先通过下图了解一下之前我们所实现的限流规则持久化方案的配置数据流向图:

  • 蓝色箭头代表了限流规则由 配置中心发起修改的更新路径

  • 橙色箭头代表了限流规则由 SentinelDashboard发起修改的更新路径

从图中可以很明显的看到, SentinelDashboard与业务服务之间本身是可以互通获取最新限流规则的,这在没有整合配置中心来存储限流规则的时候就已经存在这样的机制。最主要的区别是:配置中心的修改都可以实时的刷新到业务服务,从而被 SentinelDashboard读取到,但是对于这些规则的更新到达各个业务服务之后,并没有一个机制去同步到配置中心,作为配置中心的客户端也不会提供这样的逆向更新方法。

改造方案

关于如何改造,现来解读一下官方文档中关于这部分的说明:

要通过 Sentinel 控制台配置集群流控规则,需要对控制台进行改造。我们提供了相应的接口进行适配。

从 Sentinel 1.4.0 开始,我们抽取出了接口用于向远程配置中心推送规则以及拉取规则:

  • DynamicRuleProvider: 拉取规则

  • DynamicRulePublisher: 推送规则

对于集群限流的场景,由于每个集群限流规则都需要唯一的 flowId,因此我们建议所有的规则配置都通过动态规则源进行管理,并在统一的地方生成集群限流规则。

我们提供了新版的流控规则页面,可以针对应用维度推送规则,对于集群限流规则可以自动生成 flowId。用户只需实现 DynamicRuleProvider 和 DynamicRulePublisher 接口,即可实现应用维度推送(URL: /v2/flow)。

这段内容什么意思呢?简单的说就是 SentinelDashboard通过 DynamicRuleProviderDynamicRulePublisher两个接口来获取和更新应用的动态规则。默认情况下,就如上一节中 SentinelDashboard与各业务服务之间的两个箭头,一个接口负责获取规则,一个接口负责更新规则。

所以,只需要通过这两个接口,实现对配置中心中存储规则的读写,就能实现 SentinelDashboard中修改规则与配置中心存储同步的效果。

具体的配置数据流向图如下:

其中,绿色箭头为公共公共部分,即:不论从培中心修改,还是从 SentinelDashboard修改都会触发的操作。这样的话,从上图的两处修改起点看,所有涉及的部分都能获取到一致的限流规则了。

代码实现

下面继续说说具体的代码实现,这里参考了 SentinelDashboard源码中关于Apollo实现的测试用例。但是由于考虑到与Spring Cloud Alibaba的结合使用,略作修改。

第一步:修改 pom.xml中的Apollo OpenAPi的依赖,将 <scope>test</scope>注释掉,这样才能在主程序中使用。

  1. <dependency>

  2. <groupId>com.ctrip.framework.apollo</groupId>

  3. <artifactId>apollo-openapi</artifactId>

  4. <version>1.2.0</version>

  5. <!--<scope>test</scope>-->

  6. </dependency>

第二步:找到 resources/app/scripts/directives/sidebar/sidebar.html中的这段代码:

  1. <li ui-sref-active="active">

  2. <a ui-sref="dashboard.flowV1({app: entry.app})">

  3. <i class="glyphicon glyphicon-filter"></i>&nbsp;&nbsp;流控规则

  4. </a>

  5. </li>

修改为:

  1. <li ui-sref-active="active">

  2. <a ui-sref="dashboard.flow({app: entry.app})">

  3. <i class="glyphicon glyphicon-filter"></i>&nbsp;&nbsp;流控规则

  4. </a>

  5. </li>

第三步:在 com.alibaba.csp.sentinel.dashboard.rule包下新建一个apollo包,用来编写针对Apollo的扩展实现。

第四步:创建Apollo的配置类,定义Apollo的portal访问地址以及第三方应用访问的授权Token(通过Apollo管理员账户登录,在“开放平台授权管理”功能中创建),具体代码如下:

  1. @Configuration

  2. public class ApolloConfig {

  3. @Bean

  4. public Converter<List<FlowRuleEntity>, String> flowRuleEntityEncoder() {

  5. return JSON::toJSONString;

  6. }

  7. @Bean

  8. public Converter<String, List<FlowRuleEntity>> flowRuleEntityDecoder() {

  9. return s -> JSON.parseArray(s, FlowRuleEntity.class);

  10. }

  11. @Bean

  12. public ApolloOpenApiClient apolloOpenApiClient() {

  13. ApolloOpenApiClient client = ApolloOpenApiClient.newBuilder()

  14. .withPortalUrl("https://apollo.xxx.com") // TODO 根据实际情况修改

  15. .withToken("open api token") // TODO 根据实际情况修改

  16. .build();

  17. return client;

  18. }

  19. }

第五步:实现Apollo的配置拉取实现。

  1. @Component("flowRuleApolloProvider")

  2. public class FlowRuleApolloProvider implements DynamicRuleProvider<List<FlowRuleEntity>> {

  3. @Autowired

  4. private ApolloOpenApiClient apolloOpenApiClient;

  5. @Autowired

  6. private Converter<String, List<FlowRuleEntity>> converter;

  7. @Value("${env:DEV}")

  8. private String env;

  9. @Override

  10. public List<FlowRuleEntity> getRules(String appName) throws Exception {

  11. // flowDataId对应

  12. String flowDataId = "sentinel.flowRules";

  13. OpenNamespaceDTO openNamespaceDTO = apolloOpenApiClient.getNamespace(appName, env, "default", "application");

  14. String rules = openNamespaceDTO

  15. .getItems()

  16. .stream()

  17. .filter(p -> p.getKey().equals(flowDataId))

  18. .map(OpenItemDTO::getValue)

  19. .findFirst()

  20. .orElse("");

  21. if (StringUtil.isEmpty(rules)) {

  22. return new ArrayList<>();

  23. }

  24. return converter.convert(rules);

  25. }

  26. }

  • getRules方法中的 appName参数是Sentinel中的服务名称,这里直接通过这个名字获取Apollo配置是由于Apollo中的项目AppId与之一致,如果存在不一致的情况,则需要自己做转换。

  • 这里注入了一个 env属性,主要由于我们在使用Apollo的时候,通过启动参数来控制不同环境。所以这样就能在不同环境区分不同的限流配置了。

  • 这里的 flowDataId对应各个微服务应用中定义的 spring.cloud.sentinel.datasource.ds.apollo.flowRulesKey配置,即:Apollo中使用了什么key来存储限流配置。

  • 其他如Cluster、Namepsace都采用了默认值:default和application,这个读者有特殊需求可以做对应的修改。

第六步:实现Apollo的配置推送实现。

  1. @Component("flowRuleApolloPublisher")

  2. public class FlowRuleApolloPublisher implements DynamicRulePublisher<List<FlowRuleEntity>> {

  3. @Autowired

  4. private ApolloOpenApiClient apolloOpenApiClient;

  5. @Autowired

  6. private Converter<List<FlowRuleEntity>, String> converter;

  7. @Value("${env:DEV}")

  8. private String env;

  9. @Override

  10. public void publish(String app, List<FlowRuleEntity> rules) throws Exception {

  11. String flowDataId = "sentinel.flowRules";

  12. AssertUtil.notEmpty(app, "app name cannot be empty");

  13. if (rules == null) {

  14. return;

  15. }

  16. OpenItemDTO openItemDTO = new OpenItemDTO();

  17. openItemDTO.setKey(flowDataId);

  18. openItemDTO.setValue(converter.convert(rules));

  19. openItemDTO.setComment("modify by sentinel-dashboard");

  20. openItemDTO.setDataChangeCreatedBy("apollo");

  21. apolloOpenApiClient.createOrUpdateItem(app, env, "default", "application", openItemDTO);

  22. // Release configuration

  23. NamespaceReleaseDTO namespaceReleaseDTO = new NamespaceReleaseDTO();

  24. namespaceReleaseDTO.setEmergencyPublish(true);

  25. namespaceReleaseDTO.setReleaseComment("release by sentinel-dashboard");

  26. namespaceReleaseDTO.setReleasedBy("apollo");

  27. namespaceReleaseDTO.setReleaseTitle("release by sentinel-dashboard");

  28. apolloOpenApiClient.publishNamespace(app, env, "default", "application", namespaceReleaseDTO);

  29. }

  30. }

  • 这里的大部分内容,如:env、flowDataId、app说明与上一步中的实现一致

  • openItemDTO.setDataChangeCreatedBy("apollo");和 namespaceReleaseDTO.setReleasedBy("apollo");这两句需要注意一下,必须设置存在并且有权限的用户,不然会更新失败。

第七步:修改 com.alibaba.csp.sentinel.dashboard.controller.v2.FlowControllerV2DynamicRuleProviderDynamicRulePublisher注入的Bean,改为上面我们编写的针对Apollo的实现:

  1. @Autowired

  2. @Qualifier("flowRuleApolloProvider")

  3. private DynamicRuleProvider<List<FlowRuleEntity>> ruleProvider;

  4. @Autowired

  5. @Qualifier("flowRuleApolloPublisher")

  6. private DynamicRulePublisher<List<FlowRuleEntity>> rulePublisher;

代码示例

本文介绍内容的客户端代码,示例读者可以通过查看下面仓库中的 alibaba-sentinel-dashboard-apollo项目:

  • Github:https://github.com/dyc87112/SpringCloud-Learning/

  • Gitee:https://gitee.com/didispace/SpringCloud-Learning/

如果您对这些感兴趣,欢迎star、follow、收藏、转发给予支持!

系列回顾

  • 《使用Nacos实现服务注册与发现》

  • 《支持的几种服务消费方式》

  • 《使用Nacos作为配置中心》

  • 《Nacos配置的加载规则详解》

  • 《Nacos配置的多环境管理》

  • 《Nacos配置的多文件加载与共享配置》

  • 《Nacos的数据持久化》

  • 《Nacos的集群部署》

  • 《使用Sentinel实现接口限流》

  • 《Sentinel使用Nacos存储规则》

  • 《Sentinel使用Apollo存储规则》


推荐阅读

  • 大规模使用 Apache Kafka 的20个最佳实践

  • 永远不要在代码中使用「User」这个单词

  • 复仇者联盟与IntelliJ IDEA也很配哦

  • 各种 IntelliJ IDEA 酷炫插件推荐

  • Spring Cloud 应用注册到多个注册中心

号外:最近整理了之前编写的一系列内容做成了PDF,关注我并回复相应口令获取:

001 :领取《Spring Boot基础教程》

002 :领取《Spring Cloud基础教程》

自律到极致 - 人生才精致:第5期

活动即将发布!

关注我,加个星标,不忘签到哦~

2019

与大家聊聊技术人的斜杠生活

Spring Cloud Alibaba基础教程:Sentinel Dashboard同步Apollo存储规则相关推荐

  1. Sentinel(二十五)之Sentinel Dashboard同步Apollo存储规则

    转载自   Spring Cloud Alibaba基础教程:Sentinel Dashboard同步Apollo存储规则 在之前的两篇教程中我们分别介绍了如何将Sentinel的限流规则存储到Nac ...

  2. Spring Cloud Alibaba基础教程:Sentinel Dashboard中修改规则同步到Apollo

    在之前的两篇教程中我们分别介绍了如何将Sentinel的限流规则存储到Nacos和Apollo中.同时,在文末的思考中,我都指出了这两套整合方案都存在一个不足之处:不论采用什么配置中心,限流规则都只能 ...

  3. Spring Cloud Alibaba基础教程:Sentinel Dashboard中修改规则同步到Nacos

    上一篇我们介绍了如何通过改造Sentinel Dashboard来实现修改规则之后自动同步到Apollo.下面通过这篇,详细介绍当使用Nacos作为配置中心之后,如何实现Sentinel Dashbo ...

  4. Spring Cloud Alibaba基础教程版本升级:0.2.1-gt;0.2.2

    最近Spring Cloud Alibaba发布了最新版本,其中包含了一些比较重要的内容,比如:Nacos 1.0.0支持,Dubbo的支持等.所以把之前的系列文章中内容以及代码案例都做了升级,其中包 ...

  5. Spring Cloud Alibaba基础教程:使用Nacos实现服务注册与发现

    自Spring Cloud Alibaba发布第一个Release以来,就备受国内开发者的高度关注.虽然Spring Cloud Alibaba还没能纳入Spring Cloud的主版本管理中,但是凭 ...

  6. Spring Cloud Alibaba 基础教程:Nacos 生产级版本 0.8.0

    Spring Cloud Alibaba 基础教程:Nacos 生产级版本 0.8.0 昨晚Nacos社区发布了第一个生产级版本:0.8.0.由于该版本除了Bug修复之外,还提供了几个生产管理非常重要 ...

  7. Spring Cloud Alibaba基础教程:Nacos的集群部署

    点击蓝色"程序猿DD"关注我哟 <Spring Cloud Alibaba基础教程>连载中,关注我一起学习!前情回顾: <使用Nacos实现服务注册与发现> ...

  8. Spring Cloud Alibaba基础教程:Nacos的数据持久化

    <Spring Cloud Alibaba基础教程>连载中,关注我一起学习!前情回顾: <使用Nacos实现服务注册与发现> <支持的几种服务消费方式> <使 ...

  9. Spring Cloud Alibaba基础教程:Nacos配置的多文件加载与共享配置

    <Spring Cloud Alibaba基础教程>连载中,关注我一起学期!前情回顾: <使用Nacos实现服务注册与发现> <支持的几种服务消费方式> <使 ...

最新文章

  1. R语言对dataframe(data.table)数据分层随机抽样实战
  2. 【POJ】2828 Buy Tickets(线段树+特殊的技巧/splay)
  3. 解决启动不了VMware虚拟机以及VM升级到新的版本后出现黑屏的问题
  4. linux驱动之I2C
  5. 【网络编程】之四、socket网络编程例解
  6. 故障码123401_电力系统规划设计对电力工程设计的应用
  7. (5)hibernate多对一,一对多,一对一,多对多
  8. 自旋波matlab计算,[首藏作品](4865)从电子到磁振子,自旋波计算开启新篇章...
  9. Analyzing Storage Performance using the Windows Performance Analysis ToolKit (WPT)
  10. Duplicate property mapping of contactPhone found in
  11. 上传图片到服务器不能马上响应,用post方式上传图片到服务器
  12. 【Java】forward redirect 的差异
  13. 主机管理+堡垒机系统开发:前端批量命令结果(十二)
  14. PHP 动态设置数组索引的值
  15. 阿里云丁宇:阿里巴巴15年云原生实践
  16. Linux V4L2 框架分析
  17. FlashFXP注册码-FlashFXP密钥
  18. go语言读取xls表格xls文件操作替代解决方案
  19. vscode terminal下划线显示问题
  20. 【Shotcut】开源免费视频编辑软件 - 微信视频编辑利器

热门文章

  1. cpu密集型 计算密集型 io密集型 简介
  2. linux grub2 等待时间修改
  3. linux 内核编译错误 gcc: error: elf_i386: No such file or directory
  4. golang 并发与并行学习笔记(一)
  5. Android开发--图形图像与动画(一)--Paint和Canvas类
  6. AWS无服务开发Lambda系列之本地上传包至Lambda
  7. openstack-Mitaka Glance上传镜像报错
  8. Ansible :一个配置管理和IT自动化工具
  9. 静态html页面传递参数,javascript静态页面传值的三种方法分享
  10. apollo java客户端_02、携程Apollo Java客户端使用指南