.NET 微服務 2 架構設計理論(一)

来源:https://www.cnblogs.com/Soulless/archive/2019/08/08/11317420.html
-Advertisement-
Play Games

SOA體系架構 微服務架構 微服務特點 微服務資料庫設計 傳統單一的中心化資料庫和微服務一個服務一個資料庫 微服務和限界上下文模式的關係 微服務的邏輯架構和物理架構 分散式數據管理的挑戰和解決方案 挑戰 1:如何定義微服務邊界 首先,需要關註應用的邏輯領域模型和相關數據。必須嘗試識別同一個應用中解耦 ...


SOA體系架構

  1. 面向服務的體繫結構 (SOA) ,通過將應用程式分解為多個服務(通常為 HTTP 服務,WCF服務等),將其分為不同類型(例如子系統或層),從而來劃分應用程式的結構。
  2. 微服務源自 SOA,但 SOA 不同於微服務體繫結構。 諸如大型中央代理、組織級別的中央業務流程協調程式和企業服務匯流排 (ESB) 等功能在 SOA 中很典型。 但在大多數情況下,這些是微服務社區中的反模式。

微服務架構

  1. 微服務體繫結構是一種將伺服器應用程式生成為一組小型服務的方法。
  2. 每個服務都在自己的進程中運行,並使用 HTTP/HTTPS、WebSocket 或 AMQP 等協議與其他進程進行通信。
  3. 每個微服務在特定的上下文邊界內實現特定的端到端域或業務功能,每個微服務都必須自主開發,並且可以獨立部署。
  4. 最後,每個微服務都應擁有其自己的相關域數據模型和域邏輯(主權和分散式數據管理),並且可以基於不同的數據存儲技術(SQL、NoSQL)和不同的編程語言。
  5. 在標識和設計微服務時,只要與其他微服務不存在過多的直接依賴項,就應嘗試讓它們儘可能地小。 比微服務的大小更重要的是,它必須具有內部內聚,並且獨立於其他服務。
  6. 單獨縮放需要更多處理能力或網路帶寬以支撐需求的功能區域,而不用橫向擴展應用程式中不需要縮放的其他區域。 這意味著節省成本,因為所需硬體更少。

微服務特點

  1. 對服務和基礎結構的監視和運行狀況檢查。
  2. 服務(即雲和業務流程協調程式)的可縮放基礎結構。
  3. 多個級別的安全設計和實現:身份驗證、授權、機密管理、安全通信等。
  4. 快速應用程式交付,通常不同的團隊重點負責不同的微服務。
  5. DevOps 和 CI/CD 實踐和基礎結構。

微服務資料庫設計

傳統單一的中心化資料庫和微服務一個服務一個資料庫

  1. 單一關係型資料庫的單體式應用有兩個重要優點:在應用程式的所有資料庫表和數據層面,都支持 ACID 事務和 SQL 語言。
  2. 如果多個服務訪問相同數據,數據的更新就要求協調同步到所有服務,這會破壞微服務生命周期的自治性。當業務流程跨越多個微服務時,最終一致性是唯一的辦法。
  3. 不同微服務通常使用不同種類的資料庫。一些場景下,NoSQL 資料庫比 SQL 資料庫有著更方便的數據模型和更好的性能與擴展性。
  4. 基於微服務的應用通常會混合使用 SQL 和 NoSQL 資料庫,這種做法有時會被稱為混合數據持久化(Polyglot Persistence)。 基於容器和微服務的應用架構 這種隔離的混合數據持久化架構有很多優點,包括服務的鬆散耦合,更好的性能、擴展性,更低成本和 可管理性等。

微服務和限界上下文模式的關係

  1. 微服務的理論源自領域驅動設計(DDD)的限界上下文(BC)模式。DDD 將大型業務劃分成多個 BC,並明確它們的邊界,每個 BC 必須有自己的模型和資料庫。類似的,每個微服務也擁有跟自己相關的數據。
  2. 不同限界上下文的表示語言中的信息(主要是領域實體)可以有不同名稱,即使不同領域實體共用相同標識(即通過唯一 ID 從存儲中讀取實體)。例如在一個用戶資料的限界上下文中,用戶 User 領域實體可能跟訂單限界上下文的買家 Buyer 領域實體共用標識。
  3. 微服務與限界上下文非常類似,但微服務是一種分散式服務,每個微服務都以獨立進程的方式創建,並且必須使用先前提到的分散式協議,如 HTTP/HTTPS、WebSockets 或 AMQP。然而限界上下文模式並沒有明確一個 BC 到底是分散式服務或只是單體式部署的應用中的簡單邏輯邊界(例如常見的子系統)。

微服務的邏輯架構和物理架構

  1. 創建微服務並不要求必須使用某種技術,例如 Docker 容器就不是必需的。微服務能夠作為普通進程運行,微服務是一種邏輯架構。
  2. 即使微服務能夠以獨立的服務、進程或容器方式來實現,這種在業務微服務和物理服務或容器之間的同等性不是必要的,尤其是當我們需要創建一個由成百上千的服務組成的大型複雜應用時。系統的邏輯架構和邏輯邊界與物理或部署架構沒必要一一對應,雖然可行,但通常並不這樣做。
  3. 您或許已經確定了業務微服務或限界上下文,但不意味著最佳實現方式就是為每個業務微服務創建單獨的服務(例如作為一個 ASP.NET Web API)或單獨的 Docker 容器。沒有規定說每個業務微服務必須使用單獨服務或容器來實現。因此,業務微服務或限界上下文是一個邏輯架構,或許確實(也可以不是)與物理架構一致。重點在於,業務微服務或限界上下文必須自主地進行代碼和狀態的獨立版本控制、部署和擴展。
  4. 如圖所示,目錄業務微服務由多個服務或進程組成,它們可以是多個 ASP.NET Web API 或使用HTTP 或其他協議的服務。更重要的是,這些服務共用相同的數據,因為它們都結合在一個相同的業務領域里。

        

  5. 本例中的 Web API 服務和搜索服務使用了同一個數據源,它們共用相同的數據模型。所以在物理實現業務微服務時,對功能進行了拆分,以便能夠按需向上或向下擴展每個內部服務。例如 Web API 通常需要更多的運行實例,反之亦然。
  6. 簡而言之,微服務的邏輯架構通常與物理架構並不相同。

分散式數據管理的挑戰和解決方案

挑戰 1:如何定義微服務邊界

  • 首先,需要關註應用的邏輯領域模型和相關數據。必須嘗試識別同一個應用中解耦後的數據孤島和不同的上下文。
  • 每個上下文都可以有不同的商業語言(不同的業務術語),上下文的定義和管理應該獨立進行。在不同上下文中使用的術語和實體可能聽起來相似,但有時在特定上下文中的一個業務概念在另一個上下文中可能會被用於不同的目,甚至可能使用不同名稱。例如,同一個“用戶”,可以是身份或會員系統上下文中的“用戶”,是 CRM 中的“客戶”,甚至還是訂單上下文中的“買方”等。
  • 識別多個應用上下文以及每個上下文所對應不同領域之間邊界的方法,也能用來識別每個業務微服務和相關領域模型和數據的邊界。
  • 後面的“識別微服務的領域模型邊界”將詳細介紹識別方法和領域驅動設計。

挑戰 2:如何創建從多個微服務獲取數據的查詢

第二個挑戰在於:如何實現從多個微服務獲取數據的查詢,同時避免遠程客戶端和微服務之間不必要的通信。
例如一個移動 App 需要一個頁面來展示由購物籃、產品目錄和用戶身份微服務包含的用戶信息。
再如一個複雜的報表系統涉及到位於多個微服務的多個表。
適合的解決方案取決於查詢的複雜性。但無論如何都需要一種方式來聚合信息,以提高系統的通信效率。最流行的解決方案如下。
API 網關:對於從多個擁有不同資料庫的微服務進行的簡單數據聚合,推薦的方式是通過名為 API 網關的機制聚合微服務。然而使用這種模式時需要當心,它可能成為系統瓶頸,也可能違反微服務自治的原則。為了降低這些可能性,可以使用多個細粒度的 API 網關,每個網關主要面向系統的一個垂直“切片”即業務領域。

CQRS 查詢/讀取表:另一種聚合多個微服務數據的方案是物化視圖模式(Materialized View Pattern),這種方案會提前(在實際查詢發生前準備好非規範的數據)生成包含多個微服務數據的只讀表,並且這種表會使用適合客戶端應用需求的格式。
假設有一個移動 App 的界面,如果有一個資料庫,就可以使用一個 SQL 查詢獲取界面所需的全部數據,該查詢會針對多個表執行複雜的聯接。
但如果使用了分佈在不同微服務中的多個資料庫,就不能查詢這些資料庫並創建 SQL 聯接。此時複雜的查詢將變成巨大的挑戰。為此可以使用 CQRS 方案:在不同資料庫中創建一個只用作查詢的非規範表,這個表可以針對複雜查詢所需的數據專門設計,把應用界面所需的欄位和查詢表的欄位一一對應。這樣的查詢表還可以用在報表中。
這種方式不僅解決了最初的問題(如何跨微服務查詢和聯接),與複雜的 SQL 聯接語句相比還能進一步提升性能,因為應用所需的數據已經在查詢表裡了。當然,使用命令查詢職責分離(CQRS)的查詢/讀取表需要額外的開發工作,並且需要面對數據最終一致性問題。然而在需要高性能和高擴展性的協作場景(或者競爭場景,取決於視角)下,應該使用 CQRS 來處理多資料庫。

中心資料庫的“冷數據”:對於可能不需要實時數據的複雜報表和查詢,此時一種通用方案是將“熱數據”(微服務里的交易數據)導出為“冷數據”存儲到報表專用的大型資料庫中。這裡的中心資料庫系統可以是基於大數據的系統,如 Hadoop,也可以是數據倉庫,如 Azure SQL 數據倉庫,甚至可以是單獨的報表專用 SQL 資料庫(如果容量不是問題的話)。
需要註意的是,中心資料庫應該只用於不需要實時數據的報表查詢,作為事實數據源的原始更新和交易數據必須在微服務中。為了同步數據,可採用事件驅動通信(下一節會詳細介紹),或使用資料庫基礎結構提供的導入/導出工具。如果使用事件驅動通信的方式,整合流程將與上文提到的使用 CQRS 查詢表獲取數據的方式類似。
然而,如果應用在設計上需要不斷從多個微服務里進行聚合數據併進行複雜查詢,上述設計將變得非常糟糕,畢竟微服務之間應該儘可能地保持相互獨立(使用中心冷資料庫的報表分析系統除外)。通常在遇到此類問題後,我們也許會合併微服務。我們需要在每個微服務的自治式進化和部署,以及強依賴、高內聚和數據聚合之間進行權衡。

挑戰 3:如何在多個微服務之間實現一致性

如上文所述,每個微服務擁有的數據是私有的,只能通過微服務 API 來訪問。因此會遇到這樣一個挑戰:如何跨多個微服務保持一致性的同時實現端到端的業務邏輯。
為了分析這個問題,讓我們看看示例應用 eShopOnContainers 中的一個例子。目錄(Catalog)微服務維護著所有產品信息,包括價格。購物籃(Basket)微服務管理著用戶加入購物籃的產品臨時數據,包括添加到購物籃時的產品價格。當目錄服務中一個產品的價格發生變化後,購物籃中相同產品的價格也應該變化,另外,系統應該告訴用戶說購物籃里的某個產品的價格變了。

假如這個應用有一個單體式版本,當產品表中的價格發生變化時,產品子系統能夠簡單地使用 ACID 事務來更新購物籃表裡的價格。
然而在微服務應用里,產品表和購物籃表被各自的微服務所占有。任何微服務不應該在自己的事務中包含其他微服務的表或存儲,即使是直接查詢也是不可以的。目錄微服務不能直接更新購物籃表,因為購物籃表被購物籃微服務占有。要更新購物籃微服務,產品微服務應該使用基於非同步通信,如集成事件(消息和基於事件的通信)的最終一致性。

根據 CAP 理論,我們需要在可用性和強 ACID 一致性之間作出選擇。大多數微服務場景要求高可用性和高擴展性,而非強一致性。重要應用必須保持隨時線上,開發人員可以使用弱一致性或最終一致性的技術來做到強一致性。此外,ACID 風格或兩步提交事務不僅違背微服務原則,大多數 NoSQL 資料庫(如 Azure CosmosDB、MongoDB 等)也不支持兩步提交事務。然而,跨服務和資料庫維護數據的一致性非常重要。

因此,總結來說,解決這個問題的方法之一是,在微服務之間使用事件驅動通信和發佈訂閱系統來實現最終一致性。

挑戰 4:如何在多個微服務之間通信

跨微服務邊界的通信是一個真正的挑戰。這裡所謂的“通信”不是指該用什麼協議(HTTP 和 REST、AMQP、消息等),而是指該使用什麼樣的通信方式,尤其是如何耦合微服務。取決於耦合等級,在宕機發生時,會對系統產生不同程度的影響。
諸如微服務這樣的分散式系統中,有很多內容需要四處移動,組成分散式服務的諸多伺服器或主機等組件最終都可能面臨故障,部分宕機甚至大面積失效也會發生。面對這樣的分散式系統,需要在設計微服務和跨服務通信時就考慮到這些常見的風險。
舉例來說,假設客戶端應用發起了一個 HTTP API 請求,需要調用另一個獨立的微服務,例如訂單微服務,如果訂單微服務隨後在同一個請求/響應周期內使用 HTTP 調用另一個微服務,這就創建了一個HTTP 調用鏈條。聽起來也許合理,然而如果打算這樣做,有些重要的問題需要考慮:

  • 阻塞和性能低下。由於 HTTP 的同步本質,最初的請求在所有內部 HTTP 請求全部完成前不會獲得響應結果。假設這樣的請求量在逐步增長,同時某個中間微服務的 HTTP 調用被阻塞,結果就是性能受到影響,並且整體擴展性由於額外 HTTP 請求的增加遇到幾何級增長的影響。
  • 使用 HTTP 耦合微服務。業務微服務不應該被其他業務微服務耦合。理想情況下,它們不應該“知道”其他微服務的存在。如果我們的應用像示例一樣依靠耦合的微服務,幾乎無法實現每個微服務的自治。
  • 任何微服務引起的宕機。如果實現使用 HTTP 調用的鏈式微服務,當任何一個微服務宕機(最終每個微服務都可能宕機)時,整個微服務鏈會掛掉。微服務系統應該設計成在部分宕機情況下儘可能地繼續正常運行。即使客戶端邏輯使用了越來越快和靈敏的重試機制,HTTP 調用鏈越複雜,實現基於 HTTP 的容錯策略過程就越複雜。

實際上,如果內部微服務採用上述鏈式 HTTP 請求來通信,可能會產生這樣一種爭議:這實際上是一種單體式應用,它的進程間是基於 HTTP 的,而沒有使用進程內通信機制。
因此,為了促進微服務的自治並獲得更高彈性,應該減少使用跨服務的鏈式請求/響應通信。建議微服務間的通信只使用非同步交互,例如使用基於消息或事件的非同步通信,或者使用與原始 HTTP 請求/響應獨立的 HTTP 輪詢(Polling)方式。

參考文檔

https://docs.microsoft.com/zh-cn/dotnet/architecture/microservices/architect-microservice-container-applications/


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 一、常見的集合有哪些? Map 介面和 Collection 介面是所有集合框架的父介面。 1、Collection 介面的子介面包括:Set 介面和 List 介面; 2、Map 介面的實現類主要有:HashMap、TreeMap、Hashtable、ConcurrentHashMap 以及 Pr ...
  • 出自公眾號:大飛碼字 “怎樣才能進大廠?” “我是一個二本電腦專業的學生,怎樣才能進大廠?” “我是一個非電腦專業的學生,有機會可以進大廠嗎?” 我收到不少咨詢如何進大廠的問題,以上是一些比較典型的提問。 “怎麼可以進大廠” 這個問題,跟“怎麼可以在30歲前賺到1000萬” 和 “怎麼可以在40 ...
  • 問題描述 每一本正式出版的圖書都有一個ISBN號碼與之對應,ISBN碼包括9位數字、1位識別碼和3位分隔符,其規定格式如“x-xxx-xxxxx-x”,其中符號“-”是分隔符(鍵盤上的減號),最後一位是識別碼,例如0-670-82162-4就是一個標準的ISBN碼。ISBN碼的首位數字表示書籍的出版 ...
  • 10.17 內置函數 強調:mysql內置的函數只能在sql語句中使用 date_format: 10.171 自定義函數 函數中不要寫sql語句(否則會報錯),函數僅僅只是一個功能,是一個在sql中被應用的功能,若要想在begin...end...中寫sql,請用存儲過程. 刪除函數: 執行函數: ...
  • 4.7 推導式 列表推導式 基本格式 v1 = [i for i in 可迭代對象 ]v2 = [i for i in 可迭代對象 if 條件 ] # 條件為true才進行append 1 # 示例一 2 v1 = [ i for i in 'alex' ] # ['a','l','e','x'] ...
  • 最近趕項目忽然想到一個問題,那就是在 .Net平臺下的C#代碼是怎麼從源代碼到機器可以識別的電腦的(只怪自己上學不好好讀書,現在又要重補一遍了!!!) 話不多說直接上調研結果: 預習知識: 1: IL 是微軟.NET平臺上衍生出的一門中間語言,.NET平臺上的各種高級語言(如C#,VB,F#)的編譯 ...
  • 圖片中物體(人物,動物或其它特定物品)的精確識別與提取是人工智慧領域重要的一個方面,通過機器學習,最終能達到不需要人工干預準確的進行識別。 以雲服務的方式提供 由於這些演算法依賴於大量的訓練或基礎數據,所以,對於一些成果,以靜態的演算法,每個應用獨立去完成漫漫的訓練不是個好辦法。因此,很多類似的成果會以 ...
  • 前面已經介紹過了 ".Net Core 程式發佈到 Docker 容器" 的內容。但是每次通過 SSH 鏈接到伺服器敲命令,運行腳本也是挺麻煩的一件事。程式員是最懶的,能讓電腦解決的問題絕不手動解決,如果當我們push一次代碼後自動build代碼,自動跑單元測試,如果測試通過,自動發佈程式,如果失敗 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...