soul-admin 的数据同步流程分析

在上一篇文章中我们提到,根据官网的介绍数据配置流程 soul网关的配置数据在修改后立即同步到soul gateway 中,不需要重启,性能高,生效快。

这个特性也是网关这种中间件的基本需求,作为一个API网关,如果改一下配置还需要重启网关,基本失去了可用性。

我们现在来看一看这块是如何做到 不需要重启,并且快速生效的。

1. 寻找入口

  • 上一篇文章中,我们做了如下操作,这次我们打开浏览器的调试窗口,发现 请求的url是 http://localhost:9095/rule/1349368916835352576

在soul管理平台 【divide 插件】选择器规则列表中,找到 /http/order/findById这一条规则,点击【修改】,将【是否开启】按钮置灰。并保存设置。

2. 在项目中寻找controller

  • 在soul-admin 的controller包下面有一个 RuleController,我们发现它的请求路径就是 rule/*
@RestController
@RequestMapping("/rule")
public class RuleController {}
  • 给所有的方法打上断点,再次对规则进行修改,可以发现,点击【修改】时,由于前端需要显示规则的详情,请求的是下面的方法
/*** detail rule.** @param id rule id.* @return {@linkplain SoulAdminResult}*/@GetMapping("/{id}")public SoulAdminResult detailRule(@PathVariable("id") final String id) {RuleVO ruleVO = ruleService.findById(id);return SoulAdminResult.success(SoulResultMessage.DETAIL_SUCCESS, ruleVO);}
  • 点击保存的时候,请求的是下面的方法
    /*** update rule.** @param id      primary key.* @param ruleDTO rule.* @return {@linkplain SoulAdminResult}*/@PutMapping("/{id}")public SoulAdminResult updateRule(@PathVariable("id") final String id, @RequestBody final RuleDTO ruleDTO) {Objects.requireNonNull(ruleDTO);ruleDTO.setId(id);Integer updateCount = ruleService.createOrUpdate(ruleDTO);return SoulAdminResult.success(SoulResultMessage.UPDATE_SUCCESS, updateCount);}

3. 查看RuleService的逻辑

  1. 由于我们的主要目标是分析数据同步的流程,所以在updateRule方法中的 Integer updateCount = ruleService.createOrUpdate(ruleDTO);是我们分析的重点。也就是说RuleService的createOrUpdate 方法是我们分析的重点
  2. RuleService有一个实现类 RuleServiceImpl,我们随着断点进入 RuleServiceImplcreateOrUpdate方法
  3. 这个方法里大概扫一下,中间几行先不管,我们看一下最后的publishEvent这一行,看名字应该是将【规则被修改】这个事件发布出去。笔者猜测,这里应该就是同步数据的关键代码。
/*** create or update rule.** @param ruleDTO {@linkplain RuleDTO}* @return rows*/@Override@Transactional(rollbackFor = Exception.class)public int createOrUpdate(final RuleDTO ruleDTO) {int ruleCount;RuleDO ruleDO = RuleDO.buildRuleDO(ruleDTO);List<RuleConditionDTO> ruleConditions = ruleDTO.getRuleConditions();if (StringUtils.isEmpty(ruleDTO.getId())) {ruleCount = ruleMapper.insertSelective(ruleDO);ruleConditions.forEach(ruleConditionDTO -> {ruleConditionDTO.setRuleId(ruleDO.getId());ruleConditionMapper.insertSelective(RuleConditionDO.buildRuleConditionDO(ruleConditionDTO));});} else {ruleCount = ruleMapper.updateSelective(ruleDO);//delete rule condition then addruleConditionMapper.deleteByQuery(new RuleConditionQuery(ruleDO.getId()));ruleConditions.forEach(ruleConditionDTO -> {ruleConditionDTO.setRuleId(ruleDO.getId());RuleConditionDO ruleConditionDO = RuleConditionDO.buildRuleConditionDO(ruleConditionDTO);ruleConditionMapper.insertSelective(ruleConditionDO);});}publishEvent(ruleDO, ruleConditions);return ruleCount;}

4. 分析 publishEvent方法

  • 这个方法中有关数据同步流程的只有 最后一行,eventPublisher.publishEvent方法。我们发现使用的是ApplicationEventPublisherpublishEvent方法。
  • 根据Sping官网的介绍,想要监听 ApplicationEventPublisher发布的事件,需要实现ApplicationListener 或者 使用注解@EventListener
  • 我们在soul-admin模块中搜索(Command+Shift+F) ApplicationListenerEventListener
    。结果发现soul中使用的是实现ApplicationListener这种方式来监听事件的。
  • 有两个实现类,分别是 DataChangedEventDispatcherApplicationStartListener
   private void publishEvent(final RuleDO ruleDO, final List<RuleConditionDTO> ruleConditions) {SelectorDO selectorDO = selectorMapper.selectById(ruleDO.getSelectorId());PluginDO pluginDO = pluginMapper.selectById(selectorDO.getPluginId());List<ConditionData> conditionDataList =ruleConditions.stream().map(ConditionTransfer.INSTANCE::mapToRuleDTO).collect(Collectors.toList());// publish change event.eventPublisher.publishEvent(new DataChangedEvent(ConfigGroupEnum.RULE, DataEventTypeEnum.UPDATE,Collections.singletonList(RuleDO.transFrom(ruleDO, pluginDO.getName(), conditionDataList))));}

5. 分析 DataChangedEventDispatcher

  • 根据刚才搜索结果,ApplicationStartListenerDataChangedEventDispatcher都实现了 ApplicationListener接口,但是我们发现 在RuleServiceImplpublishEvent方法中,
    eventPublisher.publishEvent传入的是DataChangedEvent对象。所以可以排除 ApplicationStartListener
  • DataChangedEventDispatcher的 onApplicationEvent如下,大致看一下我们可以了解到,这里是几种事件类型,分别是 插件、规则、选择器、元数据、APP_AUTH等。
  • 也就是说这些事件都是在这个数据流里面的。
  • 我们从方法里的listener.onAppAuthChanged 继续追踪下去。
 @Override@SuppressWarnings("unchecked")public void onApplicationEvent(final DataChangedEvent event) {for (DataChangedListener listener : listeners) {switch (event.getGroupKey()) {case APP_AUTH:listener.onAppAuthChanged((List<AppAuthData>) event.getSource(), event.getEventType());break;case PLUGIN:listener.onPluginChanged((List<PluginData>) event.getSource(), event.getEventType());break;case RULE:listener.onRuleChanged((List<RuleData>) event.getSource(), event.getEventType());break;case SELECTOR:listener.onSelectorChanged((List<SelectorData>) event.getSource(), event.getEventType());break;case META_DATA:listener.onMetaDataChanged((List<MetaData>) event.getSource(), event.getEventType());break;default:throw new IllegalStateException("Unexpected value: " + event.getGroupKey());}}}

6. DataChangedListener的实现类

DataChangedListener有五个实现类,其中HttpLongPollingDataChangedListener继承了AbstractDataChangedListener

  • AbstractDataChangedListener
  • HttpLongPollingDataChangedListener
  • NacosDataChangedListener
  • WebsocketDataChangedListener
  • ZookeeperDataChangedListener

DataChangedEventDispatcheronApplicationEvent 方法断点信息我们可以发现,这里调用的是WebsocketDataChangedListeneronRuleChanged方法。

  • 也就是说 soul默认使用websocket来同步数据。
  • 于是我们在WebsocketDataChangedListeneronRuleChanged方法打上断点。继续调试。
   @Overridepublic void onRuleChanged(final List<RuleData> ruleDataList, final DataEventTypeEnum eventType) {WebsocketData<RuleData> configData =new WebsocketData<>(ConfigGroupEnum.RULE.name(), eventType.name(), ruleDataList);WebsocketCollector.send(GsonUtils.getInstance().toJson(configData), eventType);}

7. WebsocketDataChangedListener 的onRuleChanged方法

可以看到这个方法里,和数据同步有关的是WebsocketCollector.send方法。就是通过websocket将数据变化发送出去。

总结

  1. 我们通过一个规则的配置,找到了数据变化的入口。
  2. soul-admin的数据配置操作,进入到service层之后,通过Spring的ApplicationListener发布出去。
  3. DataChangedEventDispatcher通过实现ApplicationListener的方式监听了发布的事件
  4. DataChangedEventDispatcher中的 方法中通过调用DataChangedListener接口的方法。来执行具体的逻辑。
  5. 四个DataChangedListener的非抽象类实现分别如下,对应四种不同的同步数据的方式。
    • HttpLongPollingDataChangedListener
    • NacosDataChangedListener
    • WebsocketDataChangedListener
    • ZookeeperDataChangedListener
  6. WebsocketDataChangedListener通过websocket协议讲需要同步的数据发送给soul-bootstrap

soul从入门到进阶02——soul-admin的数据同步流程相关推荐

  1. soul从入门到进阶01——soul网关初体验

    笔者的环境 MacBook Pro 处理器 2.8 GHz 四核Intel Core i7 内存 16 GB 1600 MHz DDR3 其他环境准备 maven.jdk.git 概要简介 本篇文章主 ...

  2. soul从入门到进阶05——soul-bootstrap数据同步流程

    我们在 soul-admin的数据同步流程中分析了admin的数据同步流程,这篇我们来看看soul-bootstrap的数据同步流程 启动 soul-bootstrap 打印如下日志,我们同样从日志着 ...

  3. soul从入门到进阶04——压测soul网关

    这篇文章的主题是对soul网关进行压测 笔者的环境 MacBook Pro 处理器 2.8 GHz 四核Intel Core i7 内存 16 GB 1600 MHz DDR3 1. 压测soul-e ...

  4. 新手入门深度学习 | 2-2:结构化数据建模流程示例

    文章目录 一.准备数据 二.定义模型 三.训练模型 四.评估模型 五.使用模型 六.保存模型 1. 保存整个模型 2. 保存模型权重

  5. (进阶篇_01)Oracle数据同步3种场景

    文章目录 一.场景分析 二.实战 2.1. 创建原表表结构+初始化数据 2.2. 创建目标表表结构 2.3. 同步前效果图 2.4. 连接串 2.5. 执行同步 2.6.执行后效果图 2.7.操作记录 ...

  6. soul网关mysql8_深度解析 Soul 网关——数据同步

    引子 从官网 clone 代码下来后,依次启动 soul-admin.soul-bootstrap 和 soul-examples-http 模块,启动成功后查看 soul-admin 会发现 sou ...

  7. linux上soul网关开通,soul 网关入门篇(一):搭建篇

    前言 Soul 是一个异步的,高性能的,跨语言的,响应式的API网关.参考了Kong,Spring-Cloud-Gateway等优秀的网关后,站在巨人的肩膀上,诞生了Soul.是一个基于 实现的Web ...

  8. Soul 源码分析07 SOUL Admin 网关 Http长轮询 数据同步

    SOUL Admin & 网关 Http长轮询 数据同步 书接上回, 使用Http长轮询, 数据同步, soul-admin/src/main/resources/application.ym ...

  9. HBase入门至进阶以及开发等知识梳理

    HBase入门至进阶以及开发等知识梳理 HBase简介 hadoop简介 Hadoop是一个由Apache基金会所开发的分布式系统基础架构.用户可以在不了解分布式底层细节的情况下,开发分布式程序.充分 ...

最新文章

  1. 召集最强的智,昇腾计算产业射出一支「穿云箭」
  2. 人要有水的精神和树的精神
  3. 【学习笔记】利用Excel实现简易版大屏
  4. 走近分形与混沌(part2)-豪斯多夫维数
  5. 盛大游戏杯第十五届上海大学程序设计联赛暨上海金马五校赛
  6. Java知识系统回顾整理01基础03变量04类型转换
  7. bootstrapinput传参数_bootstrap-fileinput组件在上传时传递额外参数
  8. 【转载】robocopy的用法
  9. 在linux系统下观看和转码m3u8视频文件
  10. 牛客小白月赛2 I.艺
  11. VVC帧内预测(六)MIP
  12. 用js实现加载本地图片并显示并将图片信息上传至服务端
  13. 机器人学习笔记——机器人概述
  14. BZOJ 2140: 稳定婚姻 Tarjan Map
  15. 平板电脑安装软件_平板电脑用哪款便签软件比较好?
  16. 安卓USB开发教程 <五> 安卓 AOA 1.0
  17. 指数基金将嵌入百度搜索大数据 银行图谋独家代销权
  18. Bootstrap中glyphicon图标无法引用问题
  19. gbq可以算出土建量吗_广联达bim土建算量软件|广联达BIM土建算量GCL2013下载 - 121下载站...
  20. 【高分】ubuntu 、打开USB摄像头、Linux、USB摄像头驱动

热门文章

  1. 104. 货仓选址——绝对值不等式的运用,中位数巧用
  2. Arduino 项目笔记|旋转鞋柜#按钮去抖Debounce#电机#压力传感器
  3. 都1202年,我才知道 Tailwindcss
  4. 0601课的预习任务
  5. 读书笔记-大颠狂(非同寻常的大众幻想与群众性癫狂)
  6. Amazon推新送货无人机Prime Air
  7. 如何零基础开始学编程
  8. 3526:最简真分数 ①
  9. librosa audioread.NoBackendError
  10. Linux忘记密码的解决方法