摘要:在之前的两篇教程中我们分别介绍了如何将的限流规则存储到和中。本文以存储为例,下一篇介绍的改在示例。但是由于考虑到与的结合使用,略作修改。
在之前的两篇教程中我们分别介绍了如何将Sentinel的限流规则存储到Nacos和Apollo中。同时,在文末的思考中,我都指出了这两套整合方案都存在一个不足之处:不论采用什么配置中心,限流规则都只能通过Nacos界面或Apollo界面来完成修改才能得到持久化存储,而在Sentinel Dashboard中修改限流规则虽然可以生效,但是不会被持久化到配置中心。而在这两个配置中心里存储的数据是一个Json格式,当存储的规则越来越多,对该Json配置的可读性与可维护性会变的越来越差。所以,下面我们就来继续探讨这个不足之处,并给出相应的解决方案。本文以Apollo存储为例,下一篇介绍Nacos的改在示例。
问题分析在实际操作之前,我们先通过下图了解一下之前我们所实现的限流规则持久化方案的配置数据流向图:
蓝色箭头代表了限流规则由配置中心发起修改的更新路径
橙色箭头代表了限流规则由Sentinel Dashboard发起修改的更新路径
从图中可以很明显的看到,Sentinel Dashboard与业务服务之间本身是可以互通获取最新限流规则的,这在没有整合配置中心来存储限流规则的时候就已经存在这样的机制。最主要的区别是:配置中心的修改都可以实时的刷新到业务服务,从而被Sentinel Dashboard读取到,但是对于这些规则的更新到达各个业务服务之后,并没有一个机制去同步到配置中心,作为配置中心的客户端也不会提供这样的逆向更新方法。
改造方案关于如何改造,现来解读一下官方文档中关于这部分的说明:
要通过 Sentinel 控制台配置集群流控规则,需要对控制台进行改造。我们提供了相应的接口进行适配。
从 Sentinel 1.4.0 开始,我们抽取出了接口用于向远程配置中心推送规则以及拉取规则:
DynamicRuleProvider
: 拉取规则 DynamicRulePublisher
: 推送规则 对于集群限流的场景,由于每个集群限流规则都需要唯一的 flowId,因此我们建议所有的规则配置都通过动态规则源进行管理,并在统一的地方生成集群限流规则。
我们提供了新版的流控规则页面,可以针对应用维度推送规则,对于集群限流规则可以自动生成 flowId。用户只需实现 DynamicRuleProvider 和 DynamicRulePublisher 接口,即可实现应用维度推送(URL: /v2/flow)。
这段内容什么意思呢?简单的说就是Sentinel Dashboard通过DynamicRuleProvider和DynamicRulePublisher两个接口来获取和更新应用的动态规则。默认情况下,就如上一节中Sentinel Dashboard与各业务服务之间的两个箭头,一个接口负责获取规则,一个接口负责更新规则。
所以,只需要通过这两个接口,实现对配置中心中存储规则的读写,就能实现Sentinel Dashboard中修改规则与配置中心存储同步的效
图如下:
![图片上传中...]
其中,绿色箭头为公共公共部分,即:不论从培中心修改,还是从Sentinel Dashboard修改都会触发的操作。这样的话,从上图的两处修改起点看,所有涉及的部分都能获取到一致的限流规则了。
代码实现下面继续说说具体的代码实现,这里参考了Sentinel Dashboard源码中关于Apollo实现的测试用例。但是由于考虑到与Spring Cloud Alibaba的结合使用,略作修改。
第一步:修改pom.xml中的Apollo OpenAPi的依赖,将
com.ctrip.framework.apollo apollo-openapi 1.2.0
第二步:找到resources/app/scripts/directives/sidebar/sidebar.html中的这段代码:
修改为:
第三步:在com.alibaba.csp.sentinel.dashboard.rule包下新建一个apollo包,用来编写针对Apollo的扩展实现。
第四步:创建Apollo的配置类,定义Apollo的portal访问地址以及第三方应用访问的授权Token(通过Apollo管理员账户登录,在“开放平台授权管理”功能中创建),具体代码如下:
@Configuration public class ApolloConfig { @Bean public Converter, String> flowRuleEntityEncoder() { return JSON::toJSONString; } @Bean public Converter
> flowRuleEntityDecoder() { return s -> JSON.parseArray(s, FlowRuleEntity.class); } @Bean public ApolloOpenApiClient apolloOpenApiClient() { ApolloOpenApiClient client = ApolloOpenApiClient.newBuilder() .withPortalUrl("https://apollo.xxx.com") // TODO 根据实际情况修改 .withToken("open api token") // TODO 根据实际情况修改 .build(); return client; } }
第五步:实现Apollo的配置拉取实现。
@Component("flowRuleApolloProvider") public class FlowRuleApolloProvider implements DynamicRuleProvider> { @Autowired private ApolloOpenApiClient apolloOpenApiClient; @Autowired private Converter
> converter; @Value("${env:DEV}") private String env; @Override public List getRules(String appName) throws Exception { // flowDataId对应 String flowDataId = "sentinel.flowRules"; OpenNamespaceDTO openNamespaceDTO = apolloOpenApiClient.getNamespace(appName, env, "default", "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); } }
getRules方法中的appName参数是Sentinel中的服务名称,这里直接通过这个名字获取Apollo配置是由于Apollo中的项目AppId与之一致,如果存在不一致的情况,则需要自己做转换。
这里注入了一个env属性,主要由于我们在使用Apollo的时候,通过启动参数来控制不同环境。所以这样就能在不同环境区分不同的限流配置了。
这里的flowDataId对应各个微服务应用中定义的spring.cloud.sentinel.datasource.ds.apollo.flowRulesKey配置,即:Apollo中使用了什么key来存储限流配置。
其他如Cluster、Namepsace都采用了默认值:default和application,这个读者有特殊需求可以做对应的修改。
第六步:实现Apollo的配置推送实现。
@Component("flowRuleApolloPublisher") public class FlowRuleApolloPublisher implements DynamicRulePublisher> { @Autowired private ApolloOpenApiClient apolloOpenApiClient; @Autowired private Converter
, String> converter; @Value("${env:DEV}") private String env; @Override public void publish(String app, List
rules) throws Exception { String flowDataId = "sentinel.flowRules"; AssertUtil.notEmpty(app, "app name cannot be empty"); if (rules == null) { return; } OpenItemDTO openItemDTO = new OpenItemDTO(); openItemDTO.setKey(flowDataId); openItemDTO.setValue(converter.convert(rules)); openItemDTO.setComment("modify by sentinel-dashboard"); openItemDTO.setDataChangeCreatedBy("apollo"); apolloOpenApiClient.createOrUpdateItem(app, env, "default", "application", openItemDTO); // Release configuration NamespaceReleaseDTO namespaceReleaseDTO = new NamespaceReleaseDTO(); namespaceReleaseDTO.setEmergencyPublish(true); namespaceReleaseDTO.setReleaseComment("release by sentinel-dashboard"); namespaceReleaseDTO.setReleasedBy("apollo"); namespaceReleaseDTO.setReleaseTitle("release by sentinel-dashboard"); apolloOpenApiClient.publishNamespace(app, env, "default", "application", namespaceReleaseDTO); } }
这里的大部分内容,如:env、flowDataId、app说明与上一步中的实现一致
openItemDTO.setDataChangeCreatedBy("apollo");和namespaceReleaseDTO.setReleasedBy("apollo");这两句需要注意一下,必须设置存在并且有权限的用户,不然会更新失败。
第七步:修改com.alibaba.csp.sentinel.dashboard.controller.v2.FlowControllerV2中DynamicRuleProvider和DynamicRulePublisher注入的Bean,改为上面我们编写的针对Apollo的实现:
@Autowired @Qualifier("flowRuleApolloProvider") private DynamicRuleProvider代码示例> ruleProvider; @Autowired @Qualifier("flowRuleApolloPublisher") private DynamicRulePublisher
> rulePublisher;
本文介绍内容的客户端代码,示例读者可以通过查看下面仓库中的alibaba-sentinel-dashboard-apollo项目:
Github:https://github.com/dyc87112/SpringCloud-Learning/
Gitee:https://gitee.com/didispace/SpringCloud-Learning/
如果您对这些感兴趣,欢迎star、follow、收藏、转发给予支持!
系列回顾《Spring Cloud Alibaba基础教程:使用Nacos实现服务注册与发现》
《Spring Cloud Alibaba基础教程:支持的几种服务消费方式》
《Spring Cloud Alibaba基础教程:使用Nacos作为配置中心》
《Spring Cloud Alibaba基础教程:Nacos配置的加载规则详解》
《Spring Cloud Alibaba基础教程:Nacos配置的多环境管理》
《Spring Cloud Alibaba基础教程:Nacos配置的多文件加载与共享配置》
《Spring Cloud Alibaba基础教程:Nacos的数据持久化》
《Spring Cloud Alibaba基础教程:Nacos的集群部署》
《Spring Cloud Alibaba基础教程:使用Sentinel实现接口限流》
《Spring Cloud Alibaba基础教程:Sentinel使用Nacos存储规则》
《Spring Cloud Alibaba基础教程:Sentinel使用Apollo存储规则》
专题推荐Spring Boot基础教程
Spring Cloud基础教程
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/74441.html
摘要:下面通过这篇,详细介绍当使用作为配置中心之后,如何实现中修改规则同步到。关于下面改造的原理和分析可以见上一篇中修改规则同步到的头两节内容,这里不重复介绍了。但是由于考虑到与的结合使用,略作修改。主要就是中存储配置的和不要弄错。 上一篇我们介绍了如何通过改造Sentinel Dashboard来实现修改规则之后自动同步到Apollo。下面通过这篇,详细介绍当使用Nacos作为配置中心之后...
摘要:下面通过这篇,详细介绍当使用作为配置中心之后,如何实现中修改规则同步到。关于下面改造的原理和分析可以见上一篇中修改规则同步到的头两节内容,这里不重复介绍了。方法中的参数是中的服务名称。这里的大部分内容与上一步中的实现一致。上一篇我们介绍了如何通过改造Sentinel Dashboard来实现修改规则之后自动同步到Apollo。下面通过这篇,详细介绍当使用Nacos作为配置中心之后,如何实现S...
摘要:上一篇我们介绍了如何通过的配置功能来存储限流规则。第六步启动应用。深入思考在使用存储规则配置的时候与存储一样,对于控制台这些数据是只读的,也就是说控制台中修改规则仅存在于服务的内存中,不会修改中的配置值,重启后恢复原来的值。 上一篇我们介绍了如何通过Nacos的配置功能来存储限流规则。Apollo是国内用户非常多的配置中心,所以,今天我们继续说说Spring Cloud Alibaba...
摘要:改造背景前面我们讲解了如何对接来持久化限流的规则,对接后可以直接通过的后台进行规则的修改,推送到各个客户端实时生效。因此推送规则正确做法应该是配置中心控制台控制台配置中心数据源,而不是经数据源推送至配置中心。 改造背景 前面我们讲解了如何对接Apollo来持久化限流的规则,对接后可以直接通过Apollo的后台进行规则的修改,推送到各个客户端实时生效。 但还有一个问题就是Sentinel...
摘要:所以,在整合了做规则存储之后,需要知道在下面两个地方修改存在不同的效果控制台中修改规则仅存在于服务的内存中,不会修改中的配置值,重启后恢复原来的值。控制台中修改规则服务的内存中规则会更新,中持久化规则也会更新,重启后依然保持。 通过上一篇《使用Sentinel实现接口限流》的介绍,相信大家对Sentinel已经有了初步的认识。在Spring Cloud Alibaba的整合封装之下,接...
阅读 1167·2021-11-24 09:38
阅读 2567·2021-09-27 14:00
阅读 1126·2019-08-30 15:55
阅读 1312·2019-08-30 14:16
阅读 1455·2019-08-30 10:54
阅读 2840·2019-08-28 17:58
阅读 724·2019-08-26 13:22
阅读 1186·2019-08-26 12:01