sentinel源码分析第二篇一sentinel-dashboard控制台启动与配置

| 工作原理

  • 应用程序启动时需配置控制台地址,使得应用程序与控制台进行交互
  • 应用程序负责向控制台注册
  • 控制台负责配置规则信息
  • 应用程序通过监听等方式拉取rule到本地,等待流量到达依据配置进行限流

|| push模式工作原理

控制台配置规则

在这里插入图片描述

应用程序监听规则

在这里插入图片描述

||| 源码分析

A 控制台

  • 控制台模块是一个轻量级springboot模块
  • 用户通过FlowControllerV2配置规则并且推送zk等配置中心
    在这里插入图片描述

控制台配置

在这里插入图片描述

  • 按照类型修改DynamicRuleProvider和DynamicRulePublisher为zk,nacos等
@RestController
@RequestMapping(value = "/v2/flow")
public class FlowControllerV2 {

    private final Logger logger = LoggerFactory.getLogger(FlowControllerV2.class);

    @Autowired
    private InMemoryRuleRepositoryAdapter<FlowRuleEntity> repository;

    @Autowired
    @Qualifier("flowRuleDefaultProvider")
    private DynamicRuleProvider<List<FlowRuleEntity>> ruleProvider;
    @Autowired
    @Qualifier("flowRuleDefaultPublisher")
    private DynamicRulePublisher<List<FlowRuleEntity>> rulePublisher;
}

控制台推送

apiAddFlowRule
  • 持久化于内存
  • 推送zk
 @PostMapping("/rule")
 @AuthAction(value = AuthService.PrivilegeType.WRITE_RULE)
 public Result<FlowRuleEntity> apiAddFlowRule(@RequestBody FlowRuleEntity entity) {

     Result<FlowRuleEntity> checkResult = checkEntityInternal(entity);
     if (checkResult != null) {
         return checkResult;
     }
     entity.setId(null);
     Date date = new Date();
     entity.setGmtCreate(date);
     entity.setGmtModified(date);
     entity.setLimitApp(entity.getLimitApp().trim());
     entity.setResource(entity.getResource().trim());
     try {
         持久化于内存
         entity = repository.save(entity);
         推送zk
         publishRules(entity.getApp());
     } catch (Throwable throwable) {
         logger.error("Failed to add flow rule", throwable);
         return Result.ofThrowable(-1, throwable);
     }
     return Result.ofSuccess(entity);
 }
publishRules
  • 获取所有的规则并且推送zk
private void publishRules(/*@NonNull*/ String app) throws Exception {
     List<FlowRuleEntity> rules = repository.findAllByApp(app);
     // FlowRuleApiPublisher
     // FlowRuleApolloPublisher
     // FlowRuleNacosPublisher
     // FlowRuleZookeeperPublisher
     rulePublisher.publish(app, rules);
 }

B 客户端程序

客户端改造

  • Sentinel 针对 ZooKeeper 作了相应适配,底层可以采用 ZooKeeper 作为规则配置数据源。使用时只需添加以下依赖:
<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-datasource-zookeeper</artifactId>
    <version>x.y.z</version>
</dependency>
  • 然后创建 ZookeeperDataSource 并将其注册至对应的 RuleManager 上即可
// remoteAddress 代表 ZooKeeper 服务端的地址
// path 对应 ZK 中的数据路径
ReadableDataSource<String, List<FlowRule>> flowRuleDataSource = new ZookeeperDataSource<>(remoteAddress, path, source -> JSON.parseObject(source, new TypeReference<List<FlowRule>>() {}));
FlowRuleManager.register2Property(flowRuleDataSource.getProperty());

客户端监听与更新

  • 通过zklistener 监听规则变更
  • 全量覆盖更新规则
public class ZookeeperDataSource<T> extends AbstractDataSource<String, T> {
    ...... 删除大量代码
    private void initZookeeperListener(final String serverAddr, final List<AuthInfo> authInfos) {
        ...... 删除大量代码
       this.listener = new NodeCacheListener() {
            @Override
            public void nodeChanged() {
                zk变更
                try {
                    newValue也就是配置的rule信息 比如限流 熔断 等
                    T newValue = loadConfig();
                    RecordLog.info(String.format("[ZookeeperDataSource] New property value received for (%s, %s): %s",
                            serverAddr, path, newValue));
                    
                    更新时同时更新ruleManager的相关规则信息
                    Property对应也存在与ruleManager中
                    getProperty().updateValue(newValue);
                } catch (Exception ex) {
                    RecordLog.warn("[ZookeeperDataSource] loadConfig exception", ex);
                }
            }
        };
    }
}

更新实现

getProperty().updateValue(newValue);更新实现

  • Property注册到FlowRuleManager

FlowRuleManager.register2Property(flowRuleDataSource.getProperty());
  • 修改currentProperty规则信息为zk监听器的property
 public class FlowRuleManager {
    限流规则信息
    private static SentinelProperty<List<FlowRule>> currentProperty = new DynamicSentinelProperty<List<FlowRule>>();

    public static void register2Property(SentinelProperty<List<FlowRule>> property) {
    AssertUtil.notNull(property, "property cannot be null");
    synchronized (LISTENER) {
        currentProperty.removeListener(LISTENER);
        property.addListener(LISTENER);
        修改currentProperty规则信息为zk监听器的property
        currentProperty = property;
    }
}   

总结

  • 生成环境一般采用注册中心保障规则持久化,不会因为宕机丢失
  • 本文概述push模式的实现,sentinel还有pull,内存直接推送模式
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值