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 实现规定长久化?中的计划也只是把 流控规定
配置做了长久化。大家能够本人搜寻一下,这里不再赘述。
以上计划都存在几个有余。
- 只实现了流控规定长久化
- 须要批改源码(包含前端代码),不放面后续滚动降级
- 如果 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