关于sentinel:不改一行源码实现-sentineldashboard-所有配置支持-apollo-持久化

59次阅读

共计 4903 个字符,预计需要花费 13 分钟才能阅读完成。

sentinel-dashboard apollo 定制版

sentinel-dashboard-apollo 是从官网 Sentinel fork 的 dashboard 定制版,反对所有配置长久化到 apollo。

  • github:https://github.com/fengjx/Sen…
  • gitee:https://gitee.com/fengjx/Sent…
  • 应用文档:http://blog.fengjx.com/sentin…

sentinel-dashboard 为什么须要定制

Sentinel 是阿里巴巴开源的流量治理组件。性能十分齐全,包含了:申请过滤、降级、限流、流量监控等性能。如果对 sentinel 还不是很理解能够查看官网文档:https://sentinelguard.io/zh-c…

尽管 sentinel 的设计十分优良,基本上满足了流量治理的所有需要,然而 sentinel-dashboard(治理后盾)的配置都是存储在内存,在服务重启后就会失落。所以 sentinel 目前是不具备在生产环境上应用的。即便 sentinel 客户端是反对了从 apollo、consul、etcd、eureka、nacos、redis、spring-cloud-config、zookeeper 读取配置,然而如果不应用 dashboard,间接手动批改配置的话,官网也没有提供具体的参数配置文档,想晓得哪些参数可配置,须要本人查看源码,应用上十分不敌对。

而这个问题早在 2020 年就有人提出来了(github issue)dashboard 配置长久化性能,然而官网至今(2022-07)仍然没有实现这个性能。

https://github.com/alibaba/Se…

https://github.com/alibaba/Se…

值得一提的是,阿里云的商业版 sentinel-dashboard 是有这个性能的。并且在 test 代码中能够看到有对应长久化实现的。所以这很显著官网并不想在开源版实现这个性能,须要咱们本人去实现。这其中的原由曾经非常明显了。

计划选型

目前曾经实现的组件中,sentinel 客户端曾经反对:

  • apollo
  • consul
  • etcd
  • eureka
  • nacos
  • redis
  • spring-cloud-config
  • zookeeper

以最小化改变准则,咱们能够从下面其中一个作为长久化存储计划,否则就须要本人再开发一套客户端同步数据组件。

这里我抉择 apollo,理由是:apollo 作为配置核心,有丰盛的配置性能,与其余计划如 nacos 都要欠缺和稳固许多。而其余如 redis、zookeeper 在数据排查方面都不是太不便。

源码剖析

sentinel-dashboard 的源码构造非常简单。后端应用 spring-boot,前端应用 angular1。

咱们关上浏览器抓包工具,在界面上操作增删改查对应配置,就能够晓得对应的接口是多少,而后通过接口门路找到对应的 Controller,持续往下跟踪就能够晓得残缺的解决流程了。

例如:新增网关流控规定的接口是 /gateway/flow/new.json

通过剖析不难发现,不论是什么配置,对应增删改查的接口门路都是相似的。

sentinel 规定总共有 7 中类型,都实现了 RuleEntity 接口

咱们须要实现的也是将这 7 种数据类型长久化到 apollo。

从 sentinel 的架构设计上能够晓得分为 sentinel 客户端(也就是咱们的利用)和 sentinel-dashboard(治理后盾)。

通过剖析 FlowControllerV1 源码,能够晓得配置读写都是通过 SentinelApiClient 来实现的。

  • 读数据:通过 SentinelApiClient 申请客户端,拉取配置,而后更新到内存

  • 写数据:先保留到内存,而后调用 SentinelApiClient 将申请同步到客户端

革新实现

对于在生产环境中应用 Sentinel,官网文档中给咱们介绍了几种模式。通过下面源码剖析的流程实现的就是原始模式,咱们的革新计划是要实现推模式。

对于革新计划,如果做过这方面调研的同学,找到的材料基本上都是只实现了流量管制规定长久化,而剩下其余 6 中规定并没有实现长久化,包含姚秋辰(姚半仙)老师在极客工夫上的专栏《Spring Cloud 微服务项目实战》第 20 章节 Sentinel 实战:如何接入 Nacos 实现规定长久化?中的计划也只是把 流控规定 配置做了长久化。大家能够本人搜寻一下,这里不再赘述。

以上计划都存在几个有余。

  1. 只实现了流控规定长久化
  2. 须要批改源码(包含前端代码),不放面后续滚动降级
  3. 如果 7 中类型数据都做长久化的,那须要批改的中央会比拟多

通过下面源码剖析能够晓得,其实数据拉取和推送都是通过SentinelApiClient 的 fetchXXX(拉取数据)和 setXXX, modifyXXX(推送数据)办法来实现的,所以咱们只有把对应的办法改成从 apollo 拉取数据和将数据推送到 apollo 上就能够了,

因为 SentinelApiClient 没有定义接口,所以要在不扭转源码的状况下扭转它的默认行为,就要通过 aop 来实现了。

上面是实现网关流控规定读写 apollo 的示例代码。

@Aspect
@Component
public class SentinelApiClientAspect {private static final Logger LOG = LoggerFactory.getLogger(SentinelApiClientAspect.class);

    @SuppressWarnings("PMD.ThreadPoolCreationRule")
    private static final ExecutorService EXECUTOR = Executors.newSingleThreadExecutor(new NamedThreadFactory("sentinel-dashboard-api-aspect"));

    @Resource
    private DynamicRuleStoreFactory factory;


    @Pointcut("execution(public * com.alibaba.csp.sentinel.dashboard.client.SentinelApiClient.fetchGatewayFlowRules(..))")
    public void fetchGatewayFlowRulesPointcut() {}

    @Pointcut("execution(public * com.alibaba.csp.sentinel.dashboard.client.SentinelApiClient.modifyGatewayFlowRules(..))")
    public void modifyGatewayFlowRulesPointcut() {}

    /**
     * 拉取网关流控规定配置
     */
    @Around("fetchGatewayFlowRulesPointcut()")
    public Object fetchGatewayFlowRules(final ProceedingJoinPoint pjp) throws Throwable {return fetchRulesWithCompletableFuture(pjp, RuleType.GW_FLOW);
    }

    /**
     * 推送网关流控规定配置
     */
    @Around("modifyGatewayFlowRulesPointcut()")
    public Object modifyGatewayFlowRules(final ProceedingJoinPoint pjp) throws Throwable {return publishRules(pjp, RuleType.GW_FLOW);
    }

    // 两头省略了局部代码,残缺代码能够从 github 查看

    private Object fetchRules(ProceedingJoinPoint pjp, RuleType ruleType) throws Throwable {DynamicRuleStore<?> dynamicRuleStore = factory.getDynamicRuleStoreByType(ruleType);
        if (dynamicRuleStore == null) {return pjp.proceed();
        }
        Object[] args = pjp.getArgs();
        String app = (String) args[0];
        return dynamicRuleStore.getRules(app);
    }

    private CompletableFuture<Object> fetchRulesWithCompletableFuture(ProceedingJoinPoint pjp, RuleType ruleType) {return CompletableFuture.supplyAsync(() -> {
            try {return fetchRules(pjp, ruleType);
            } catch (Throwable e) {throw new RuntimeException("fetch rules error:" + ruleType.getName(), e);
            }
        }, EXECUTOR);
    }


    @SuppressWarnings("unchecked")
    private boolean publishRules(ProceedingJoinPoint pjp, RuleType ruleType) {DynamicRuleStore<RuleEntity> dynamicRuleStore = factory.getDynamicRuleStoreByType(ruleType);
        Object[] args = pjp.getArgs();
        String app = (String) args[0];
        List<RuleEntity> rules = (List<RuleEntity>) args[3];
        try {dynamicRuleStore.publish(app, rules);
            return true;
        } catch (Exception e) {LOG.error("publish rules error", e);
            return true;
        }
    }

    private CompletableFuture<Void> publishRulesWithCompletableFuture(ProceedingJoinPoint pjp, RuleType ruleType) {return CompletableFuture.runAsync(() -> publishRules(pjp, ruleType), EXECUTOR);
    }
}

对应 apollo 读写数据的代码在 test 包下曾经有了,拿过去稍加改变就能够了

<img width=”50%” src=”./01.sentinel-dashboard-test-apollo.png” />

残缺的代码实现能够在 github 上查看:https://github.com/fengjx/Sen…,整个改变没有批改一行源码,只是新增了一些类,不便后续降级不会引起代码抵触。

革新后的成果

dashboard 配置

apollo 配置

降级 & 版本保护

本我的项目从 sentinel 官网 github 仓库 fork,只针对 dashboard 模块进行批改,放弃与官网公布版本同步批改,版本对应关系

Sentinel sentinel-dashboard-apollo 阐明
branch – master branch: dashboard/apollo/master 放弃最新版本与官网 master 同步
tag – 1.8.4 branch: dashboard/apollo/1.8.4 从官网公布的 tag checkout 进去进行批改
tag – 1.8.4 tag: dashboard/apollo/v1.8.4 批改实现后公布 tag

相干文档

  • Sentinel 控制台
  • 在生产环境中应用 Sentinel

正文完
 0