微服務之間的調用關系如何處理,才能防止循環依賴


在微服務架構中,循環依賴是常見的設計問題,可能導致系統部署失敗、啟動順序沖突、故障排查困難等問題。處理循環依賴的核心原則是通過架構設計打破依賴閉環,以下是具體的解決方案:
1. 重新劃分服務邊界(根本解決)
循環依賴往往源于服務職責劃分不合理,應從業務領域出發重新梳理邊界:
按聚合根拆分:基于領域驅動設計(DDD),將緊密關聯的業務能力聚合到同一服務,避免跨服務的強依賴。
提取共享能力:若兩個服務都依賴某部分功能,可將這部分功能拆分為獨立的新服務(如用戶認證服務、配置服務),讓原服務都依賴這個新服務,打破閉環。
示例:
訂單服務(A)依賴庫存服務(B),而庫存服務(B)又依賴訂單服務(A)查詢訂單狀態 → 可將 “訂單狀態查詢” 中與庫存相關的部分拆分到新的 “訂單快照服務”(C),讓 A 和 B 都依賴 C,消除 A?B 的循環。
2. 引入事件驅動架構(異步解耦)
用事件驅動替代同步調用,通過消息隊列傳遞事件,切斷直接依賴:
服務 A 完成操作后,發布事件到消息隊列(如 Kafka、RabbitMQ)。
服務 B 訂閱該事件,無需主動調用 A,而是 A 和 B 之間不再有直接依賴。
示例:
訂單服務(A)創建訂單后,發布 “訂單創建事件” → 庫存服務(B)訂閱該事件并扣減庫存,無需調用 A;B 扣減庫存后發布 “庫存變更事件” → A 訂閱該事件更新訂單狀態。此時 A 和 B 通過事件間接交互,無直接依賴。
3. 使用中介者模式(引入中間層)
在循環依賴的服務之間增加一個中介服務(如 API 網關、聚合服務),統一處理交互邏輯:
原服務 A 和 B 不再直接調用,而是都調用中介服務。
中介服務協調 A 和 B 的交互,避免 A?B 的直接依賴。
適用場景:
當服務間依賴關系復雜(如 A?B、B?C、C?A 的三角依賴),中介服務可簡化調用鏈路。
4. 避免雙向同步調用
若必須同步通信,需確保調用方向單向化:
明確服務的 “上游” 和 “下游” 關系,只允許上游調用下游,禁止下游反向調用上游。
若下游需要上游數據,可通過緩存(如 Redis)或數據同步(如 CDC 工具)將上游數據同步到下游,避免反向調用。
示例:
用戶服務(上游)調用訂單服務(下游)查詢訂單 → 訂單服務若需用戶信息,可通過緩存獲取(用戶服務更新時同步數據到緩存),而非直接調用用戶服務。
5. 依賴注入與接口抽象(代碼層面規避)
在代碼實現層面,通過接口抽象和依賴注入(DI)降低耦合:
定義獨立的接口模塊(如 API 包),服務 A 和 B 都依賴接口,而非具體實現。
避免在服務內部硬編碼對其他服務的直接引用,通過配置或注冊中心動態獲取依賴。
注意:此方法僅緩解代碼層面的耦合,無法解決架構層面的循環依賴,需配合架構設計使用。
6. 部署與啟動策略(臨時規避)
若循環依賴暫時無法重構,可通過部署策略臨時規避:
允許部分失敗啟動:服務啟動時不強制檢查依賴服務是否可用,待依賴服務啟動后再重試連接。
固定啟動順序:在部署腳本中定義嚴格的啟動順序(如先啟動 “基礎服務”,再啟動 “依賴服務”)。
缺點:僅為權宜之計,無法從根本上解決問題,且會增加運維復雜度。
總結
處理循環依賴的優先級為:
重構服務邊界(最徹底)→ 2. 事件驅動異步解耦(推薦)→ 3. 引入中介層 → 4. 單向同步 + 數據同步 → 5. 臨時部署策略。
核心思想是通過 “職責清晰化、交互異步化、依賴單向化” 打破閉環,同時結合領域設計和架構評審,在設計階段避免循環依賴的產生。

重新劃分服務邊界的核心是基于業務領域的 “高內聚、低耦合” 原則,將緊密相關的業務能力聚合到同一服務,將無關或弱相關的能力拆分到其他服務。以下結合通過具體案例說明實現方法和思路。

案例背景:循環依賴的初始狀態

假設我們有兩個服務存在循環依賴:

  • 訂單服務(Order Service):負責訂單創建、支付狀態更新。
  • 庫存服務(Inventory Service):負責庫存扣減、庫存查詢。

問題

  • 訂單創建時,訂單服務需要調用庫存服務扣減庫存(Order → Inventory)。
  • 庫存不足時,庫存服務需要調用訂單服務取消訂單(Inventory → Order)。
    形成循環依賴:Order ? Inventory。

步驟 1:梳理業務流程與依賴點

先明確兩個服務的核心操作和依賴關系:

  1. 訂單服務核心操作:

    • 創建訂單(需檢查并扣減庫存)
    • 更新訂單狀態(包括因庫存不足被取消的狀態)
  2. 庫存服務核心操作:

    • 扣減庫存(若庫存不足,需通知訂單取消)
    • 查詢庫存
  3. 依賴痛點:庫存服務為了處理 “庫存不足” 的情況,必須直接調用訂單服務的 “取消訂單” 接口,形成反向依賴。

步驟 2:基于領域邊界重新劃分職責

通過分析發現:“訂單取消” 是訂單領域的核心能力,不應由庫存服務直接觸發,而應通過事件通知的方式間接觸發。因此可以:

  • 訂單服務:保留 “創建訂單”“取消訂單”“更新狀態” 等核心能力,負責訂單全生命周期管理。
  • 庫存服務:專注于庫存管理,僅負責 “扣減庫存”“查詢庫存”,不再直接調用訂單服務,而是通過事件告知庫存狀態。

步驟 3:引入事件機制打破循環

在兩個服務之間引入事件總線(如 Kafka),用異步事件替代直接調用:

  1. 訂單服務創建訂單時,同步調用庫存服務扣減庫存(同步調用)。
  2. 若庫存不足,庫存服務發布 “庫存不足事件”(而非直接調用訂單服務)。
  3. 訂單服務訂閱 “庫存不足事件”,收到事件后自行執行 “取消訂單” 操作。

此時依賴關系變為單向:
Order → Inventory(同步調用),Inventory → 事件總線 → Order(異步通知),循環依賴被打破。

步驟 4:進一步優化(可選)提取共享能力

如果多個服務都需要 “訂單狀態查詢” 能力(如庫存服務、物流服務、支付服務),可進一步拆分:

  • 新增訂單查詢服務(Order Query Service):提供訂單狀態查詢的只讀接口,基于訂單服務的數據庫副本或緩存提供數據。
  • 原訂單服務僅保留寫操作(創建、更新、取消),其他服務若需查詢訂單,均調用訂單查詢服務。

效果:減少對核心訂單服務的直接依賴,避免因查詢操作過多導致的性能問題。

最終服務邊界與依賴關系

plaintext

┌─────────────────┐       ┌─────────────────┐
│   訂單服務      │       │   庫存服務      │
│ - 創建訂單      │?──────┤ - 扣減庫存      │
│ - 取消訂單      │       │ - 查詢庫存      │
│ - 更新狀態      │──────?│                 │
└────────┬────────┘       └────────┬────────┘│                        │▼                        ▼
┌─────────────────┐       ┌─────────────────┐
│   事件總線      │?──────┤  訂單查詢服務   │
│ - 庫存不足事件  │       │ - 訂單狀態查詢  │
│ - 訂單創建事件  │──────?│                 │
└─────────────────┘       └─────────────────┘

核心原則總結

  1. 按業務領域聚合:將同一業務流程中強相關的操作(如訂單的創建、取消、狀態更新)放在同一服務。
  2. 避免跨領域強依賴:不同領域服務間通過 “同步調用 + 異步事件” 組合,同步用于必要的即時交互,異步用于狀態通知。
  3. 拆分 “讀” 與 “寫”:核心服務專注于寫操作,讀操作可拆分到專門的查詢服務,降低依賴復雜度。

通過這種方式,服務邊界清晰,依賴關系單向可控,從根本上避免了循環依賴。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/93939.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/93939.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/93939.shtml

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

相關文章

粗糧廠的基于flink的汽車實時數倉解決方案

基于flink的實時數倉解決方案1 背景2 業務模型1 業務框架2 難點痛點3技術選型1 計算引擎2 中間存儲3 查詢引擎4 flink計算架構設計1 純實時架構2 純實時定期補充離線數據3 純實時定期刷新過期binlog4 lamdba 分字段更新 歷史過期數據刷新5 痛點解決delta joinmerge-enginehol…

Datawhale AI夏令營---coze空間共學

1.進入coze空間 2.點擊免費使用 3.點擊制作播客,微信上面選好鏈接 徹底搞懂深度學習-模型訓練和推理(動圖講解) 4.運行過程 5.音頻鏈接 https://lf-bot-studio-plugin-resource.coze.cn/obj/bot-studio-platform-plugin-tos/sami_podcast…

遙感機器學習入門實戰教程|Sklearn案例⑥:網格搜索與超參數優化

在前幾篇案例中,有同學在后臺留言:“模型的參數到底怎么調?比如 SVM 的 C 和 γ,隨機森林的樹數和深度,要怎么選才能得到最優結果呢?”這是一個非常經典的問題:參數選不好,模型效果差…

論文精讀(三)|智能合約漏洞檢測技術綜述

筆者鏈接:撲克中的黑桃A 專欄鏈接:論文精讀 本文關鍵詞:智能合約;合約安全;合約可靠性;合約質量保障;漏洞檢測;合約程序分析 引 諸位技術同仁: 本系列將系統精讀的方式,深入剖析計算機科學頂級期刊/會議論文&#…

YOLO --- YOLO11模型以及項目詳解

YOLO — YOLO11模型以及項目詳解 文章目錄YOLO --- YOLO11模型以及項目詳解一,開源地址二,重要模塊2.1 C3K22.2 C2PSA2.3 檢測頭三,網絡結構3.1 整體結構劃分3.2 Backbone 結構分析(從下往上看)3.3 結構分析&#xff0…

Debezium監聽MySQL binlog并實現有狀態重啟

Debezium實現MySQL數據監聽了解Debezium? 本期主要內容實現步驟1. 新建Maven工程2.導入依賴3.核心代碼編寫4.offset的存儲5.OffsetBackingStore實現jdbc模式6.運行結果總結了解Debezium 官網:https://debezium.io/ Debezium是一組分布式服務,用于捕獲數…

InfluxDB 存儲優化:TSM 文件管理與空間回收(一)

一、InfluxDB 與 TSM 文件初相識**在數字化時代,數據量呈爆發式增長,尤其是時間序列數據,如服務器監控指標、傳感器讀數、金融交易記錄等,它們都帶有時間戳,記錄著事物隨時間的變化。InfluxDB 作為一款高性能的開源時序…

macos使用FFmpeg與SDL解碼并播放H.265視頻

效果: 安裝依賴: brew install ffmpeg brew install sdl2 brew install x265 確認x265已啟用 查看x265版本 工程CMakeLists.txt

C#開源庫ACadSharp讀取dwg圖元的示例

文章目錄介紹數據示例讀取圖元屬性介紹 開源庫ACadSharp的地址:https://github.com/DomCR/ACadSharp 可以在NuGet中搜索到該庫并安裝。 數據示例 數據是一個繪制了以下簡單圖元的dwg數據: 讀取圖元屬性 創建了.net6控制臺項目,通過NuG…

【UniApp打包鴻蒙APP全流程】如何配置并添加UniApp API所需的鴻蒙系統權限

一、前言:為什么選擇 UniApp 打包鴻蒙應用? 隨著鴻蒙生態的快速發展,越來越多開發者希望將現有跨平臺項目快速接入鴻蒙系統。而 UniApp 作為國內領先的跨平臺開發框架,憑借其“一次開發,多端發布”的特性,…

STM32-FreeRTOS快速入門指南(下)

第十一章 FreeRTOS事件標志組 1. 事件標志組簡介 事件標志組與信號量一樣屬于任務間同步的機制,但是信號量一般用于任務間的單事件同步,對于任務間的多事件同步,僅使用信號量就顯得力不從心了。 FreeRTOS 提供的事件標志組可以很好的處理多事…

KTH7812磁編碼器芯片完全支持ABZ和UVW輸出模式

KTH7812磁編碼器芯片完全支持ABZ和UVW輸出模式,具體功能細節如下:🔧 1. ABZ輸出特性 分辨率可編程:支持 4~4096步/圈(對應1~1024個脈沖周期/圈),用戶可通過配置寄存器自定義分辨率。 輸出頻率…

Android為ijkplayer設置音頻發音類型usage

官方文檔 多區音頻路由 | Android Open Source Projecthttps://source.android.google.cn/docs/automotive/audio/audio-multizone-routing?hlzh-cn 背景 車機系統開發多分區(zone)功能,可以實現同一個app通過設置,在不同分…

C++ 循環:從入門到精通的深度解析

《C++ 循環:從入門到精通的深度解析》 目錄 循環的本質與編程價值 三大基礎循環結構詳解 循環控制語句:break與continue的魔法 嵌套循環:構建復雜邏輯的基石 現代C++循環特性(C++11+) 循環性能優化與常見陷阱 實戰案例:算法與工程中的循環應用 面試題深度解析與編程技巧…

| `cat /etc/os-release` | 發行版詳細信息(如 Ubuntu、CentOS) |

在 Linux 或類 Unix 系統中,最簡潔的命令查看操作系統類型是: uname -s? 輸出示例: LinuxDarwin(macOS)FreeBSD 等🔍 說明: uname:顯示系統信息-s:僅顯示操作系統內核名…

Maya 3D建模:點、線、面、創建多邊面

目錄 一 點、線、面 二 創建多邊面 一 點、線、面 鼠標放在模型上 按住鼠標右鍵:就可以選擇點 線 面 shift 加選點線面 ctrl 減選點線面 頂點面:是一個檢查模式,觀察有無錯誤 選擇面,單擊一個面,按住shift鍵 同時…

CXR-LT 2024:一場關于基于胸部X線的長尾、多標簽和零樣本疾病分類的MICCAI挑戰賽|文獻速遞-深度學習人工智能醫療圖像

Title題目CXR-LT 2024: A MICCAI challenge on long-tailed, multi-label, and zero-shotdisease classification from chest X-rayCXR-LT 2024:一場關于基于胸部X線的長尾、多標簽和零樣本疾病分類的MICCAI挑戰賽01文獻速遞介紹CXR-LT系列是一項由社區推動的計劃&a…

拆解本地組策略編輯器 (gpedit.msc) 的界面和功能

我們來詳細拆解本地組策略編輯器 (gpedit.msc) 的界面和功能。打開后,你會看到一個標準的微軟管理控制臺 (MMC) 窗口,主要分為三個部分。 這是一個典型的本地組策略編輯器界面,我們將其分為三個主要部分進行講解: +-----------------------------------------------+----…

[NCTF2019]True XML cookbook

TRY 嘗試XML外部實體注入 <?xml version"1.0" encoding"utf-8" ?> <!DOCTYPE user[<!ENTITY flag SYSTEM "file://./doLogin.php"> ]> <user><username> &flag; </username><password>1</pa…

嵌入式硬件篇---模塊使用

在電子開發、自動化控制等領域&#xff0c;“模塊” 是實現特定功能的標準化組件&#xff08;可以理解為 “功能積木”&#xff09;。不同模塊分工明確&#xff0c;比如有的負責感知環境&#xff08;傳感器&#xff09;&#xff0c;有的負責通信&#xff08;藍牙 / WiFi&#x…