变更通知在开源SpringBoot/SpringCloud微服务中的最佳实践

目录导读

  • 变更通知在开源SpringBoot/SpringCloud微服务中的最佳实践
    • 1. 什么是变更通知
    • 2. 变更通知的场景分析
    • 3. 变更通知的技术方案
      • 3.1 变更通知的技术实现方案
    • 4. 变更通知的最佳实践总结
    • 5. 参考资料

变更通知在开源SpringBoot/SpringCloud微服务中的最佳实践

1. 什么是变更通知

  • 变更通知是指数据发生变化后,相对实时地通知到关联端的技术实现方案;
  • 变更通知是在服务拆分的发展过程中,逐渐衍生出的,解耦关联服务的一种技术解决方案;
  • 微服务架构中常说的配置中心就是变更通知的技术集成方案;

2. 变更通知的场景分析

  • 变更通知首先是数据发生了变化,数据变化后的通知实现,数据变化的交互场景列举分析如下:
通知类型模块1模块1数据变更模块2模块2实时变更技术实现方式本文讨论范围
消息通知前端1前端2前端总线等
消息保存前端1后端2Post Ajax请求等
消息通知后端1前端2WebSocket等推送到前端(推数据),也叫消息推送
消息通知后端1前端2前端Http主动轮询(拉数据)
变更通知后端1后端2Redis/ZooKeeper/Etcd/Nacos/MQ等

总结:

  • 变更通知首先是数据(也可叫消息,下同。)发生了变化,然后引起了关联方同步变化;
  • 数据变化可以发生在前端后端之间的任意组合之间,包括前端+前端前端+后端后端+后端,一般只有后端+后端的连锁反应叫变更通知,这也是本文关注的重点;
  • 上表串联了所有常规的交互过程,大家也可以从中理解消息通知变更通知之间的关联关系:只是不同交互方式下的数据变化的叫法罢了;
  • 前端感知后端的数据变化,主要有前端轮询后端推送两种,二者技术实现差异较大,前者技术实现简单,但是后端资源消耗较大,无法承担高并发;后者技术实现较复杂,但是点对点通信效率高(长连接)。这不是本文讲述的重点,但希望能够类比分析下各种交互方式下的技术方案,做到一通百通;
  • 变更通知主要关注的是后端数据变化,但是不是所有的后端数据变化都需要变更通知。一般来说,跨了服务实例,才比较适用变更通知,单个服务实例内,完全可以通过接口引用等方式自行获取到变化的数据;
  • 本文重点关注的是变更通知而不是配置中心,像NacosSpringCloud-ConfigApollo配置中心并不会过多介绍;
  • 本文主要关注后端与后端之间的数据变化机制及技术实现,其发展阶段如下:
变更类型应用发展阶段技术方案技术实现说明
主动获取单实例共享数据库查询数据库数据库查询量不大
主动获取单实例共享内存缓存查询时先查缓存数据库查询量非常大
主动获取多实例分布式缓存使用读写性能极高的分布式缓存组件如:Memcached/Redis
变更通知多实例消息中间件Redis/ZooKeeper/Etcd/MQ/binlog+canal等订阅通知机制

总结:

  • 变更通知是随着服务的高并发、分布式发展而发展的,在单体架构时,因为都在一个服务内,仅通过数据库或者共享缓存即可达到数据共享的目的,不一定需要变更通知
  • 在微服务架构中,也可以采用共享缓存方案,而不是必须使用变更通知变更通知适用于并发高、实时性要求高,且服务解耦的场景;
  • 实时是一个相对概念,在变更通知语境里,一般是指异步监听的方式获取变化的数据(专业术语叫订阅通知);

3. 变更通知的技术方案

  • 变更通知中间件种类较多,基于本人的理解,对比列举如下:
中间件类型实现特点适用场景不足补充说明
Redis基于key的订阅/通知并发高、消息量大NoSQL可读性差,持久化不是必选项,存在数据丢失和审计风险Redis是极度常用的高效内存组件,建议优选;
ZooKeeper基于分布式临时Node创建的订阅/通知可靠性高、实时性高使用的是内存存储,不适合高并发和大量数据的消息变更场景一般是项目中有ZooKeeper,正好可以用作变更通知组件,而不是因为变更通知诉求而引入ZooKeeper
Etcd基于分布式的Key/Value创建的订阅/通知可靠性高、实时性高使用的是内存存储,不适合高并发和大量数据的消息变更场景Etcd的实现参考了ZooKeeper,一个是Go语言编写、一个是Java语言
MQ异步消息协议可靠性高、并发高、消息量大组件较重包括:Kafka/RocketMQ/RabbitMQ/ActiveMQ等,非常适合电商优惠卷等场景使用
binlog+canal针对MySQL的数据变更监听方案直接监听数据库表字段变化只适用于MySQL,而MySQL使用量正逐年下降只是监听了MySQL的数据表变化,一般还需要配合其它的变更通知组件来配合使用,如:ZooKeeper
配置中心服务端推送把配置中心组件当成业务配置中心组件重、可靠性低、实时性低配置中心严格来说是个变更通知的解决方案,而上面列举的中间件是纯技术组件,二者的维度不太一样;
配置中心一般和注册中心配合使用,因为它本身也需要注册至服务中心,如:ApolloSpringCloud-Config;有些干脆就被注册中心兼任,如Nacos

总结:

  • 变更通知一般来说是微服务中的增强功能,不建议因为有变更通知需求就新增一个组件。如果系统中已经有了Redis,就建议优先选择Redis,因为其性能高、消息存储量大。但Redis是NoSQL存储结构,可读性较差;Redis也有可能没有开启持久化导致数据丢失;Redis也缺失了类似关系数据库自带的操作审计,一旦数据出现了异常,将很难知道是谁做了什么;
  • ZooKeeper/Etcd则比较适合系统中已经引入该组件了,且变更通知消息数量较小的场景;
  • MQ比较适用于可靠性高、消息量巨大的场景,值得单独引入。如:大型电商的活动卡券配置等场景;
  • binlog+canal这个特定组合一般不建议单独使用,一般是canal把变更数据发送给其它变更通知Server,然后在业务模块订阅变更通知Server的这个变化数据,并做相应的业务处理。其它Server可以是ZooKeeper/Etcd/Redis等;
  • 一般来说,配置中心包含了单独的配置规则界面和变更通知的能力,拆箱即用,效果当然较好。但并不是所有的变更通知都需要重量级的配置中心,不是非要在配置中心去配置变更数据的,就都没有必要用它;业务需要使用到配置中心组件时,建议在选定注册中心后,再来决策选择其配置中心
  • 变更通知有非常多的实现方式,讲讲本人实际经历的业务场景:
场景类型业务诉求微服务架构微服务技术栈方案说明
场景1DB数据变更立即触发定时任务微服务架构spring+mysql+binlog+canal+ZooKeeper基于spring自研微服务框架
场景2-1业务阈值在1天内生效微服务云原生架构SpringBoot+Redis+PostgreSQL1.依赖k8s提供服务发现等;
2.依赖redis限流;
场景2-2业务阈值在1天内生效微服务私部署架构SpringBoot1.部署至客户机房,不依赖Redis/DB;
2.使用Nginx做负载均衡,也不需要服务注册和发现;
场景3业务阈值在5分钟内生效微服务云原生架构SpringBoot+Redis1.依赖k8s提供服务发现等;
2.依赖redis限流;
场景4业务阈值在立即生效SpringCloud微服务架构SpringBoot+Redis+Nacos1.依赖Nacos提供服务发现等;
2.依赖redis限流;
  • 补充说下上述业务场景的技术选型限定条件:
    • 场景1:DB数据变更立即触发定时任务:当时刚刚时兴微服务,我所在公司1的部门基于spring自研了一个低代码平台,我们需要实时监听数据的变化,以触发不同的定时任务,正好平台中也引入了canal开源组件,用于监听mysql的binlog
      变化,于是就选定了canal方案,这样就不用定时轮询数据库了,也不用和增删改数据的服务耦合了;
    • 场景2:业务阈值在1天内生效场景2-1场景2-2其实对应同一个目标:我所在公司2的部门希望设计一套架构、一套代码,既能满足云上微服务架构,也能够支持私部署微服务架构。当时云上选型为云原生微服务架构,完全基于k8s+非侵入式的链路追踪中间件,我们基本上只使用最简单的SpringBoot+Redis即可;而私部署则继续沿用了这套架构和代码,只不过移除了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就已经存在于项目中了;
  • 如果数据量非常庞大,还要支持复杂的规则,比如消息确认和重传等,则建议采用MQ(Kafka/RocketMQ/RabbitMQ/ActiveMQ);
  • 有些场景下的变更通知非常适合使用配置中心,如:SpringCloud-Gateway的路由规则yaml配置,就非常适合放在配置中心(如:Nacos等);当然如果使用的是k8s,则建议直接使用其ConfigMap;

5. 参考资料

  • [1]深入浅出阿里数据同步神器:Canal原理+配置+实战全网最全解析!
  • [2]图文解析 Nacos 配置中心的实现
  • [3]apollo 基本原理
  • [4]Spring Cloud Config 原理简介和实现

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/43099.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Ubuntu在自己的项目中使用pcl

1、建立一个文件夹,如pcl_demos,里面建立一个.cpp文件和一个cmake文件 2、打开终端并进入该文件夹下,建立一个build文件夹存放编译的结果并进入该文件夹 3、对上一级进行编译 cmake .. 4、生成可执行文件 make 5、运行该可执行文件 6、可视…

微服务中间件-分布式缓存Redis

分布式缓存 a.Redis持久化1) RDB持久化1.a) RDB持久化-原理 2) AOF持久化3) 两者对比 b.Redis主从1) 搭建主从架构2) 数据同步原理(全量同步)3) 数据同步原理(增量同步) c.Redis哨兵1) 哨兵的作用2) 搭建Redis哨兵集群3) RedisTem…

金融语言模型:FinGPT

项目简介 FinGPT是一个开源的金融语言模型(LLMs),由FinNLP项目提供。这个项目让对金融领域的自然语言处理(NLP)感兴趣的人们有了一个可以自由尝试的平台,并提供了一个与专有模型相比更容易获取的金融数据。…

VS2015项目中,MFC内存中调用DLL函数(VC6生成的示例DLL)

本例主要讲一下,用VC6如何生成DLL,用工具WinHex取得DLL全部内容,VC2015项目加载内存中的DLL函数,并调用函数的示例。 本例中的示例代码下载,点击可以下载 一、VC6.0生成示例DLL项目 1.新建项目,…

SQL Server Express 自动备份方案

文章目录 SQL Server Express 自动备份方案前言方案原理SQL Server Express 自动备份1.创建存储过程2.设定计划任务3.结果检查sqlcmd 参数说明SQL Server Express 自动备份方案 前言 对于许多小型企业和个人开发者来说,SQL Server Express是一个经济实惠且强大的数据库解决方…

Spring Framework中的Bean生命周期

目录 一.Bean生命周期的简介 1.基本概念 2.Spring生命周期的几大阶段 3.注意点及小结 4.生活案例 5.Spring容器管理JavaBean的初始化过程 二. Bean的单例选择与多例选择 1.单例选择与多例选择的优缺点 1.1单例模式的优点: 1.2单例模式的缺点: 1…

JDK 8 升级 JDK 17 全流程教学指南

JDK 8 升级 JDK 17 首先已有项目升级是会经历一个较长的调试和自测过程来保证允许和兼容没有问题。先说几个重要的点 遇到问题别放弃仔细阅读报错,精确到每个单词每一行,不是自己项目的代码也要点进去看看源码到底是为啥报错明确你项目引入的包&#x…

第三届“赣政杯”网络安全大赛 | 赛宁筑牢安全应急防线

​​为持续强化江西省党政机关网络安全风险防范意识,提高信息化岗位从业人员基础技能,提升应对网络安全风险处置能力。由江西省委网信办、江西省发展改革委主办,江西省大数据中心、国家计算机网络与信息安全管理中心江西分中心承办&#xff0…

Qt扫盲-QTableView理论总结

QTableView理论总结 一、概述二、导航三、视觉外观四、坐标系统五、示例代码1. 性别代理2. 学生信息模型3. 对应视图 一、概述 QTableView实现了一个tableview 来显示model 中的元素。这个类用于提供之前由QTable类提供的标准表,但这个是使用Qt的model/view架构提供…

MySQL 存储过程

create procedure 存储过程名 (in | out | INPUT 参数名 参数类型,。。。) 【characteristics 。。。】begin存储过程体end存储过程的参数类型 IN 、OUT、INPUT 都可以在一个存储过程带多个 没有参数(无参数无返回)仅…

边缘网络的作用及管理工具

自从引入软件即服务 (SaaS) 以来,它一直引领着全球按需软件部署创新的竞赛,它提供的灵活性以及其云计算架构带来的易于集成使其成为交付业务应用程序的标准。 在 SaaS 模型中,最佳用户体验的三重奏涉及无缝设置、低延…

JMeter 特殊组件-逻辑控制器与BeanShell PreProcessor 使用示例

文章目录 前言JMeter 特殊组件-逻辑控制器与BeanShell PreProcessor 使用示例1. 逻辑控制器使用1.1. While Controller 使用示例1.2. 如果(If)控制器 使用示例 2. BeanShell PreProcessor 使用示例 前言 如果您觉得有用的话,记得给博主点个赞…

Java课题笔记~ SpringBoot简介

1. 入门案例 问题导入 SpringMVC的HelloWord程序大家还记得吗? SpringBoot是由Pivotal团队提供的全新框架,其设计目的是用来简化Spring应用的初始搭建以及开发过程 原生开发SpringMVC程序过程 1.1 入门案例开发步骤 ①:创建新模块&#…

设计模式-过滤器模式(使用案例)

过滤器模式(Filter Pattern)或标准模式(Criteria Pattern)是一种设计模式,这种模式允许开发人员使用不同的标准来过滤一组对象,通过逻辑运算以解耦的方式把它们连接起来。这种类型的设计模式属于结构型模式…

服务器安装centos7踩坑

1、制作启动工具 下载iso https://developer.aliyun.com/mirror/?spma2c6h.25603864.0.0.20387abbo2RFbn http://mirrors.aliyun.com/centos/7.9.2009/isos/x86_64/?spma2c6h.25603864.0.0.1995f5ad4AhJaW下载 UltraISO https://cn.ultraiso.net/插入u盘启动 到了如图所示页面…

nginx php-fpm安装配置

nginx php-fpm安装配置 nginx本身不能处理PHP,它只是个web服务器,当接收到请求后,如果是php请求,则发给php解释器处理,并把结果返回给客户端。 nginx一般是把请求发fastcgi管理进程处理,fascgi管理进程选…

架构演进及常用架构

1架构演进及常用架构 1.1单体分层架构 1.2 多应用微服务架构 1.3 分布式集群部署 部署 CDN 节点: 用户访问量的增加意味着用户地域的分散请求,如果所有请求都直接发送中心服务器的话,距离越远,响应速度越差,这时就需…

【编织时空四:探究顺序表与链表的数据之旅】

本章重点 链表的分类 带头双向循环链表接口实现 顺序表和链表的区别 缓存利用率参考存储体系结构 以及 局部原理性。 一、链表的分类 实际中链表的结构非常多样,以下情况组合起来就有8种链表结构: 1. 单向或者双向 2. 带头或者不带头 3. 循环或者非…

yolov5封装进ros系统

一,要具备ROS环境 ROS环境搭建可以参考我之前的文章 ROS参考文章1 ROS参考文章2   建立ROS工作空间 ROS系统由自己的编译空间规则。 cd 你自己想要的文件夹(我一般是home目录) mkdir -p (你自己的文件夹名字,比如我是yolov5…

C++的stack和queue+优先队列

文章目录 什么是容器适配器底层逻辑为什么选择deque作为stack和queue的底层默认容器优先队列优先队列的模拟实现stack和queue的模拟实现 什么是容器适配器 适配器是一种设计模式(设计模式是一套被反复使用的、多数人知晓的、经过分类编目的、代码设计经验的总 结),…