變更通知在開源SpringBoot/SpringCloud微服務中的最佳實踐

目錄導讀

  • 變更通知在開源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等?

總結:

  • 變更通知首先是數據(也可叫消息,下同。)發生了變化,然后引起了關聯方同步變化;
  • 數據變化可以發生在前端后端之間的任意組合之間,包括前端+前端前端+后端后端+后端,一般只有后端+后端的連鎖反應叫變更通知,這也是本文關注的重點;
  • 上表串聯了所有常規的交互過程,大家也可以從中理解消息通知變更通知之間的關聯關系:只是不同交互方式下的數據變化的叫法罷了;
  • 前端感知后端的數據變化,主要有前端輪詢后端推送兩種,二者技術實現差異較大,前者技術實現簡單,但是后端資源消耗較大,無法承擔高并發;后者技術實現較復雜,但是點對點通信效率高(長連接)。這不是本文講述的重點,但希望能夠類比分析下各種交互方式下的技術方案,做到一通百通;
  • 變更通知主要關注的是后端數據變化,但是不是所有的后端數據變化都需要變更通知。一般來說,跨了服務實例,才比較適用變更通知,單個服務實例內,完全可以通過接口引用等方式自行獲取到變化的數據;
  • 本文重點關注的是變更通知而不是配置中心,像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.pswp.cn/news/43099.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/43099.shtml
英文地址,請注明出處:http://en.pswp.cn/news/43099.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Ubuntu在自己的項目中使用pcl

1、建立一個文件夾,如pcl_demos,里面建立一個.cpp文件和一個cmake文件 2、打開終端并進入該文件夾下,建立一個build文件夾存放編譯的結果并進入該文件夾 3、對上一級進行編譯 cmake .. 4、生成可執行文件 make 5、運行該可執行文件 6、可視…

最強自動化測試框架Playwright(30)-JS句柄

在 Playwright 中,JSHandle 是一個表示瀏覽器中 JavaScript 對象的類。它提供了與網頁中的 JavaScript 對象進行交互和操作的方法。 可以通過調用 Playwright中的 evaluateHandle 或 evaluate 方法來獲取 JSHandle from playwright.sync_api import sync_playwrig…

微服務中間件-分布式緩存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)感興趣的人們有了一個可以自由嘗試的平臺,并提供了一個與專有模型相比更容易獲取的金融數據。…

Java根據List集合中的一個字段對集合進行去重

利用HashSet 創建了一個HashSet用于存儲唯一的字段值&#xff0c;并創建了一個新的列表uniqueList用于存儲去重后的對象。遍歷原始列表時&#xff0c;如果字段值未在HashSet中出現過&#xff0c;則將其添加到HashSet和uniqueList中。 List<Person> originalList new Ar…

VS2015項目中,MFC內存中調用DLL函數(VC6生成的示例DLL)

本例主要講一下&#xff0c;用VC6如何生成DLL&#xff0c;用工具WinHex取得DLL全部內容&#xff0c;VC2015項目加載內存中的DLL函數&#xff0c;并調用函數的示例。 本例中的示例代碼下載&#xff0c;點擊可以下載 一、VC6.0生成示例DLL項目 1.新建項目&#xff0c;…

mysql中的is null和空字符串

相比于oracle&#xff0c;mysql中的is null 和空坑就沒那么多&#xff0c;直接寫就行。 不為空 and (username is not null and username !)注&#xff1a; 不為空中間用的是and。 為空 and (username is null or username !)注&#xff1a; 為空中間用的是or。

java應用運行在docker,并且其他組件也在docker

docker啟動redis容器 # create redis docker run -d --name redis-container -p 6379:6379 redis:latest創建java 應用 dockerfile FROM openjdk:17##Pre-create related directories RUN mkdir -p /data/etax/ms-app WORKDIR /data/etax/ms-appEXPOSE 10133 COPY ./target…

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單例模式的優點&#xff1a; 1.2單例模式的缺點&#xff1a; 1…

JDK 8 升級 JDK 17 全流程教學指南

JDK 8 升級 JDK 17 首先已有項目升級是會經歷一個較長的調試和自測過程來保證允許和兼容沒有問題。先說幾個重要的點 遇到問題別放棄仔細閱讀報錯&#xff0c;精確到每個單詞每一行&#xff0c;不是自己項目的代碼也要點進去看看源碼到底是為啥報錯明確你項目引入的包&#x…

第三屆“贛政杯”網絡安全大賽 | 賽寧筑牢安全應急防線

??為持續強化江西省黨政機關網絡安全風險防范意識&#xff0c;提高信息化崗位從業人員基礎技能&#xff0c;提升應對網絡安全風險處置能力。由江西省委網信辦、江西省發展改革委主辦&#xff0c;江西省大數據中心、國家計算機網絡與信息安全管理中心江西分中心承辦&#xff0…

Qt掃盲-QTableView理論總結

QTableView理論總結 一、概述二、導航三、視覺外觀四、坐標系統五、示例代碼1. 性別代理2. 學生信息模型3. 對應視圖 一、概述 QTableView實現了一個tableview 來顯示model 中的元素。這個類用于提供之前由QTable類提供的標準表&#xff0c;但這個是使用Qt的model/view架構提供…

MySQL 存儲過程

create procedure 存儲過程名 &#xff08;in | out | INPUT 參數名 參數類型&#xff0c;。。。&#xff09; 【characteristics 。。。】begin存儲過程體end存儲過程的參數類型 IN 、OUT、INPUT 都可以在一個存儲過程帶多個 沒有參數&#xff08;無參數無返回&#xff09;僅…

ProGuard + SpringBoot3 + JDK17

1、pom依賴 <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation"http://maven.apache.org/POM/4.…

android平臺的語音聊天助手源碼

目錄 1 android平臺的語音聊天助手源碼 1.1 Setting 1.1.1 onChildClick 1.1.2 if (groupPosition == 0) {// 語音識別設置 android平臺的語音聊天助手源碼 Setting onChildClick

神經網絡基礎-神經網絡補充概念-11-向量化邏輯回歸

概念 通過使用 NumPy 數組來進行矩陣運算&#xff0c;將循環操作向量化。 向量化的好處在于它可以同時處理多個樣本&#xff0c;從而加速計算過程。在實際應用中&#xff0c;尤其是處理大規模數據集時&#xff0c;向量化可以顯著提高代碼的效率。 代碼實現-以邏輯回歸為例 i…

邊緣網絡的作用及管理工具

自從引入軟件即服務 &#xff08;SaaS&#xff09; 以來&#xff0c;它一直引領著全球按需軟件部署創新的競賽&#xff0c;它提供的靈活性以及其云計算架構帶來的易于集成使其成為交付業務應用程序的標準。 在 SaaS 模型中&#xff0c;最佳用戶體驗的三重奏涉及無縫設置、低延…

JMeter 特殊組件-邏輯控制器與BeanShell PreProcessor 使用示例

文章目錄 前言JMeter 特殊組件-邏輯控制器與BeanShell PreProcessor 使用示例1. 邏輯控制器使用1.1. While Controller 使用示例1.2. 如果&#xff08;If&#xff09;控制器 使用示例 2. BeanShell PreProcessor 使用示例 前言 如果您覺得有用的話&#xff0c;記得給博主點個贊…

Java課題筆記~ SpringBoot簡介

1. 入門案例 問題導入 SpringMVC的HelloWord程序大家還記得嗎&#xff1f; SpringBoot是由Pivotal團隊提供的全新框架&#xff0c;其設計目的是用來簡化Spring應用的初始搭建以及開發過程 原生開發SpringMVC程序過程 1.1 入門案例開發步驟 ①&#xff1a;創建新模塊&#…