网站开发 男生,网站建设汇卓,如何建网站并做推广,房地产项目网站目录导读 变更通知在开源SpringBoot/SpringCloud微服务中的最佳实践1. 什么是变更通知2. 变更通知的场景分析3. 变更通知的技术方案3.1 变更通知的技术实现方案 4. 变更通知的最佳实践总结5. 参考资料 变更通知在开源SpringBoot/SpringCloud微服务中的最佳实践
1. 什么是变更通… 目录导读 变更通知在开源SpringBoot/SpringCloud微服务中的最佳实践1. 什么是变更通知2. 变更通知的场景分析3. 变更通知的技术方案3.1 变更通知的技术实现方案 4. 变更通知的最佳实践总结5. 参考资料 变更通知在开源SpringBoot/SpringCloud微服务中的最佳实践
1. 什么是变更通知
变更通知是指数据发生变化后相对实时地通知到关联端的技术实现方案变更通知是在服务拆分的发展过程中逐渐衍生出的解耦关联服务的一种技术解决方案微服务架构中常说的配置中心就是变更通知的技术集成方案
2. 变更通知的场景分析
变更通知首先是数据发生了变化数据变化后的通知实现数据变化的交互场景列举分析如下
通知类型模块1模块1数据变更模块2模块2实时变更技术实现方式本文讨论范围消息通知前端1✔前端2✔前端总线等✖消息保存前端1✔后端2✔Post Ajax请求等✖消息通知后端1✔前端2✔WebSocket等推送到前端推数据也叫消息推送✖消息通知后端1✔前端2✔前端Http主动轮询拉数据✖变更通知后端1✔后端2✔Redis/ZooKeeper/Etcd/Nacos/MQ等✔ 总结 变更通知首先是数据也可叫消息下同。发生了变化然后引起了关联方同步变化数据变化可以发生在前端和后端之间的任意组合之间包括前端前端、前端后端、后端后端一般只有后端后端的连锁反应叫变更通知这也是本文关注的重点上表串联了所有常规的交互过程大家也可以从中理解消息通知和变更通知之间的关联关系只是不同交互方式下的数据变化的叫法罢了前端感知后端的数据变化主要有前端轮询和后端推送两种二者技术实现差异较大前者技术实现简单但是后端资源消耗较大无法承担高并发后者技术实现较复杂但是点对点通信效率高长连接。这不是本文讲述的重点但希望能够类比分析下各种交互方式下的技术方案做到一通百通变更通知主要关注的是后端数据变化但是不是所有的后端数据变化都需要变更通知。一般来说跨了服务实例才比较适用变更通知单个服务实例内完全可以通过接口引用等方式自行获取到变化的数据本文重点关注的是变更通知而不是配置中心像Nacos、SpringCloud-Config、Apollo等配置中心并不会过多介绍 本文主要关注后端与后端之间的数据变化机制及技术实现其发展阶段如下
变更类型应用发展阶段技术方案技术实现说明主动获取单实例共享数据库查询数据库数据库查询量不大主动获取单实例共享内存缓存查询时先查缓存数据库查询量非常大主动获取多实例分布式缓存使用读写性能极高的分布式缓存组件如Memcached/Redis变更通知多实例消息中间件Redis/ZooKeeper/Etcd/MQ/binlogcanal等订阅通知机制 总结 变更通知是随着服务的高并发、分布式发展而发展的在单体架构时因为都在一个服务内仅通过数据库或者共享缓存即可达到数据共享的目的不一定需要变更通知在微服务架构中也可以采用共享缓存方案而不是必须使用变更通知。变更通知适用于并发高、实时性要求高且服务解耦的场景实时是一个相对概念在变更通知语境里一般是指异步监听的方式获取变化的数据专业术语叫订阅通知 3. 变更通知的技术方案
变更通知中间件种类较多基于本人的理解对比列举如下
中间件类型实现特点适用场景不足补充说明Redis基于key的订阅/通知并发高、消息量大NoSQL可读性差持久化不是必选项存在数据丢失和审计风险Redis是极度常用的高效内存组件建议优选ZooKeeper基于分布式临时Node创建的订阅/通知可靠性高、实时性高使用的是内存存储不适合高并发和大量数据的消息变更场景一般是项目中有ZooKeeper正好可以用作变更通知组件而不是因为变更通知诉求而引入ZooKeeperEtcd基于分布式的Key/Value创建的订阅/通知可靠性高、实时性高使用的是内存存储不适合高并发和大量数据的消息变更场景Etcd的实现参考了ZooKeeper一个是Go语言编写、一个是Java语言MQ异步消息协议可靠性高、并发高、消息量大组件较重包括Kafka/RocketMQ/RabbitMQ/ActiveMQ等非常适合电商优惠卷等场景使用binlogcanal针对MySQL的数据变更监听方案直接监听数据库表字段变化只适用于MySQL而MySQL使用量正逐年下降只是监听了MySQL的数据表变化一般还需要配合其它的变更通知组件来配合使用如ZooKeeper配置中心服务端推送把配置中心组件当成业务配置中心组件重、可靠性低、实时性低配置中心严格来说是个变更通知的解决方案而上面列举的中间件是纯技术组件二者的维度不太一样配置中心一般和注册中心配合使用因为它本身也需要注册至服务中心如Apollo、SpringCloud-Config有些干脆就被注册中心兼任如Nacos 总结 变更通知一般来说是微服务中的增强功能不建议因为有变更通知需求就新增一个组件。如果系统中已经有了Redis就建议优先选择Redis因为其性能高、消息存储量大。但Redis是NoSQL存储结构可读性较差Redis也有可能没有开启持久化导致数据丢失Redis也缺失了类似关系数据库自带的操作审计一旦数据出现了异常将很难知道是谁做了什么ZooKeeper/Etcd则比较适合系统中已经引入该组件了且变更通知消息数量较小的场景MQ比较适用于可靠性高、消息量巨大的场景值得单独引入。如大型电商的活动卡券配置等场景binlogcanal这个特定组合一般不建议单独使用一般是canal把变更数据发送给其它变更通知Server然后在业务模块订阅变更通知Server的这个变化数据并做相应的业务处理。其它Server可以是ZooKeeper/Etcd/Redis等一般来说配置中心包含了单独的配置规则界面和变更通知的能力拆箱即用效果当然较好。但并不是所有的变更通知都需要重量级的配置中心不是非要在配置中心去配置变更数据的就都没有必要用它业务需要使用到配置中心组件时建议在选定注册中心后再来决策选择其配置中心 变更通知有非常多的实现方式讲讲本人实际经历的业务场景
场景类型业务诉求微服务架构微服务技术栈方案说明场景1DB数据变更立即触发定时任务微服务架构springmysqlbinlogcanalZooKeeper基于spring自研微服务框架场景2-1业务阈值在1天内生效微服务云原生架构SpringBootRedisPostgreSQL1.依赖k8s提供服务发现等2.依赖redis限流场景2-2业务阈值在1天内生效微服务私部署架构SpringBoot1.部署至客户机房不依赖Redis/DB2.使用Nginx做负载均衡也不需要服务注册和发现场景3业务阈值在5分钟内生效微服务云原生架构SpringBootRedis1.依赖k8s提供服务发现等2.依赖redis限流场景4业务阈值在立即生效SpringCloud微服务架构SpringBootRedisNacos1.依赖Nacos提供服务发现等2.依赖redis限流
补充说下上述业务场景的技术选型限定条件 场景1DB数据变更立即触发定时任务当时刚刚时兴微服务我所在公司1的部门基于spring自研了一个低代码平台我们需要实时监听数据的变化以触发不同的定时任务正好平台中也引入了canal开源组件用于监听mysql的binlog 变化于是就选定了canal方案这样就不用定时轮询数据库了也不用和增删改数据的服务耦合了场景2业务阈值在1天内生效场景2-1和场景2-2其实对应同一个目标我所在公司2的部门希望设计一套架构、一套代码既能满足云上微服务架构也能够支持私部署微服务架构。当时云上选型为云原生微服务架构完全基于k8s非侵入式的链路追踪中间件我们基本上只使用最简单的SpringBootRedis即可而私部署则继续沿用了这套架构和代码只不过移除了k8s、redis、服务注册和服务发现仅使用Nginx做服务负载均衡场景3业务阈值在5分钟内生效则是我所在公司2的业务团队认为一天生效对业务影响较大需要调整为5分钟内生效场景4业务阈值在立即生效则是我所在公司2的另一个新项目在场景3代码架构的基础上使用SpringCloud套件替换了k8s同时业务也更复杂业务上必须保证实时生效 单独来说上面的每个业务场景都可以多种技术实现。本人仅站在过来人的角度逐一展开分析。
3.1 变更通知的技术实现方案 场景1的实现方案单独部署了一个Canal服务用于监听binlog变化在Canal服务中又集成了ZooKeeper客户端Canal收到变化的数据后通过ZooKeeper推送至订阅的业务微服务 场景2的实现方案经过分析私部署不需要变更通知因为私部署不带数据库业务阈值是配在yaml中修改后隔离重启服务即可云原生微服务则因为数据刷新后1天内生效即可但为了考虑私部署和云原生架构的统一所以采用了Guava持久层的本地缓存方案Guava缓存的有效期设置为24小时过期后就会重新从PostgreSQL/yaml中获取。但由于云原生的运维不接收直接修改数据库阈值数据于是又配套开发了一个小的命令行工具也可以做成Web运维平台用于专门更改数据库表的字段值。 从中可以看出 因为要兼顾云原生和私部署场景所以需要选择两种场景下都能使用的本地缓存方案Guava因为缓存刷新的时效要求低不使用变更通知也是完全可行的。 场景3的实现方案场景3其实是场景2的延续只是现在数据生效的时间从1天变成了5分钟考虑技术方案的延续性在云原生方案中新增了一个定时任务Redis用于刷新缓存交互逻辑如下图所示 说明 第1次请求到业务服务时Guava缓存中也没有数据则需要业务服务查询一次Database并把数据缓存至Guava流程为蓝色①→②箭头所示第2次请求到业务服务时Guava缓存中已经有了数据则只需要直接返回数据即可流程为绿色①所示当用运维工具更新数据时同时也会清理掉Redis的缓存标记一旦ScheduleJob获取的Redis Key采用redis的setNX语法不一致时则会让Guava缓存失效流程为红色的①→②→③→④箭头所示后面再有请求过来时会重新执行上面的第1步和第2步 总结 场景3仅在场景2的基础上迭代增加了虚线框框中的2个小功能点代码就可以了代码延续性较好ScheduleJob设置为1分钟就可以满足5分钟内生效的业务诉求了回过头来看看场景2其实并没有做变更通知只是采用了Guava自带的缓存过期机制而已场景3其实也可以采用Guava自带的缓存过期机制但是会导致微服务需要频繁的穿透缓存去查询数据库得不偿失场景3的实际做法则兼顾了准实时性和便利性只有命令行工具变更了数据时缓存才会刷新。另外场景3也没有做到变更通知只是变相的达到了准实时的变更通知的效果。 场景4的实现方案场景4是在复用场景3的代码框架的基础上要求做到数据变更实时通知。此时项目中虽然已引入了SpringCloud的多个组件但是业务参数配置都有单独的配置界面无须使用配置中心。考虑到Redis其实也有变更通知的能力此处正好可以在场景3的基础上继续迭代去掉ScheduleJob增加Redis订阅通知的代码即可。
4. 变更通知的最佳实践总结
需要搞清楚什么是变更通知什么是配置中心不要因为有变更通知的需求就上配置中心这样有可能把系统搞得非常复杂好的设计都要顺势而为首先需要了解系统的需求到底是什么是不是一定要做变更通知如本人列举的项目实践中就多次未使用变更通知组件但是达到了变更通知的效果如果只需要做变更通知不需要独立的配置中心建议优选Redis因为它可以兼顾业务限流、高速缓存、不规则数据的处理(NoSQL)等很有可能Redis就已经存在于项目中了如果数据量非常庞大还要支持复杂的规则比如消息确认和重传等则建议采用MQKafka/RocketMQ/RabbitMQ/ActiveMQ有些场景下的变更通知非常适合使用配置中心如SpringCloud-Gateway的路由规则yaml配置就非常适合放在配置中心如Nacos等当然如果使用的是k8s则建议直接使用其ConfigMap
5. 参考资料
[1]深入浅出阿里数据同步神器Canal原理配置实战全网最全解析[2]图文解析 Nacos 配置中心的实现[3]apollo 基本原理[4]Spring Cloud Config 原理简介和实现