微服務架構:介紹、分布式與集群、架構四要素、設計模式、架構說明、項目結構說明、通訊方式、架構演進


參考

書籍:《ASP.NET Core 微服務實戰》

微軟微服務框架 dapr V1.0版本 2021-02-17 正式發布

.Net 微服務架構技術棧的那些事

Asp.Net Core微服務初體驗

.NET Core微服務系列基礎文章

百度百科說明: 微服務

知乎上:什么是微服務架構

微軟文檔:.NET 微服務 - 體系結構電子書    項目示例: eShopOnContainers GitHub

ABP微服務示例 --模塊化 + ddd + 微服務 + 容器化

[Abp vNext微服務實踐] - 文章目錄

Blog.Core官網 -- 前后端分離(.net core + vue) + 微服務 + 容器化 + CI/CD

surging: surging作者博客   surging git地址   -- dotnetty + 微服務 + websocket-sharp + rpc + Mqtt

騰飛.NET 雲原生架構師訓練營筆記

分布式與集群

分布式

參考:分布式系統--百度百科

分布式就是把一個系統拆分成多個服務節點,每個節點部署在不同的服務器上,可以理解為把一個事情分為多個簡單的步驟。

集群

集群就把一個服務復制部署在多台電腦上,多台電腦同時執行同一個服務節點的功能,可以理解為多個一起做同一個步驟。

集群一般需要通過分布式技術來保證數據一致和同步等問題,例如分布式事務、分布式緩存等

對稱集群與非對稱集群:

  • 對稱集群:     集群實例角色地位相同    ,特點:數據計算
  • 非對稱集群 :集群實例角色地位不相同 ,特點:數據存儲,redis集群是非對稱集群

微服務中先分布式后集群

先分布式:例如12306,會分成登錄、查票、訂單、支付等多個服務。

后集群:根據請求訪問量多的服務弄成集群模式,例如12306中的查票服務。

微服務是什么

微服務是一個支持特定業務場景的獨立部署單元。它借助語義化版本管理、定義良好的 API 與其他后端服務交互。它的天然特點就是嚴格遵守單一職責原則。

包含以下特點

  • 每個微服務獨立完整性:,雖然每個微服務會有重復部分,但是不能提取出來放到公共服務中,因為要保證每個微服務都有獨立性完整的功能,以便於橫向集群擴展
  • 公共服務:包括注冊、通信、認證、限流、負載均衡、熔斷、日志等,這些公共服務有變化時不會影響到單個微服務

架構四要素:

  1. 問題:確定問題,怎么做    
  2. 問題邊界 (約束 ):誰的問題,給出約束
  3. 生命周期:
  4. 拆分:根據問題的生命周期拆分

設計模式

轉載自:六種微服務架構的設計模式

聚合器(常用)

這是一種最常用也最簡單的設計模式,如下圖所示:

聚合器調用多個服務實現應用程序所需的功能。它可以是一個簡單的Web頁面,將檢索到的數據進行處理展示。它也可以是一個更高層次的組合微服務,對檢索到的數據增加業務邏輯后進一步發布成一個新的微服務,這符合DRY原則。另外,每個服務都有自己的緩存和數據庫。如果聚合器是一個組合服務,那么它也有自己的緩存和數據庫。聚合器可以沿X軸和Z軸獨立擴展。

異步消息傳遞(常用)

備注:abp的微服務demo就是使用此模式

雖然REST設計模式非常流行,但它是同步的,會造成阻塞。因此部分基於微服務的架構可能會選擇使用消息隊列代替REST請求/響應,如下圖所示:

數據共享

自治是微服務的設計原則之一,就是說微服務是全棧式服務。但在重構現有的“單體應用(monolithic application)”時,SQL數據庫反規范化可能會導致數據重復和不一致。因此,在單體應用到微服務架構的過渡階段,可以使用這種設計模式,如下圖所示:

在這種情況下,部分微服務可能會共享緩存和數據庫存儲。不過,這只有在兩個服務之間存在強耦合關系時才可以。對於基於微服務的新建應用程序而言,這是一種反模式。

代理

這是聚合器模式的一個變種,如下圖所示:

在這種情況下,客戶端並不聚合數據,但會根據業務需求的差別調用不同的微服務。代理可以僅僅委派請求,也可以進行數據轉換工作。

鏈式

這種模式在接收到請求后會產生一個經過合並的響應,如下圖所示:

在這種情況下,服務A接收到請求后會與服務B進行通信,類似地,服務B會同服務C進行通信。所有服務都使用同步消息傳遞。在整個鏈式調用完成之前,客戶端會一直阻塞。因此,服務調用鏈不宜過長,以免客戶端長時間等待。

分支

這種模式是聚合器模式的擴展,允許同時調用兩個微服務鏈,如下圖所示:

微服務通訊方式

一般是:外部通信使用http,內部通信使用grpc

對微服務通訊方式RPC vs REST的理解

比較 gRPC 服務和 HTTP API

Http通信

IHttpClientFactory:組件的工廠抽象,該組件可使用自定義配置為給定邏輯名稱創建 HttpClient 實例

IHttpClientFactory.CreateClient(String):使用與 name 指定的邏輯名稱相對應的配置來創建和配置 HttpClient 實例。

HttpClient:提供基本類,用於發送 HTTP 請求和接收來自通過 URI 確認的資源的 HTTP 響應。

HttpClient.PostAsync(string requestUri, HttpContent content):以異步操作將 POST 請求發送給指定 URI。

HttpContent:表示 HTTP 實體正文和內容標頭的基類。

StringContent(String, Encoding, String):創建 System.Net.Http.StringContent 類的新實例

HttpResponseMessage:表示包括狀態代碼和數據的 HTTP 響應消息。

在 ASP.NET Core 中使用 IHttpClientFactory 發出 HTTP 請求

.net core HttpClient 使用之掉坑解析(一)

核心的4行代碼

private readonly IHttpClientFactory httpClientFactory;
//
HttpClient httpClient = httpClientFactory.CreateClient(String); 
//
HttpContent hc = new StringContent(String, Encoding, String); 
//
HttpResponseMessage response = await httpClient.PostAsync(string requestUri, HttpContent content);

封裝好的注冊通信客戶端類 ConsulHttpClient 的完整代碼如下:

using Newtonsoft.Json;
using RuanMou.MicroService.Core.Cluster;
using RuanMou.MicroService.Core.Registry;
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;

namespace RuanMou.MicroService.Core.HttpClientConsul
{
    /// <summary>
    /// consul httpclient擴展
    /// </summary>
   public class ConsulHttpClient
   {
        private readonly IServiceDiscovery serviceDiscovery;
        private readonly ILoadBalance loadBalance;
        private readonly IHttpClientFactory httpClientFactory;
        public ConsulHttpClient(IServiceDiscovery serviceDiscovery,
                                    ILoadBalance loadBalance,
                                    IHttpClientFactory httpClientFactory)
        {
            this.serviceDiscovery = serviceDiscovery;
            this.loadBalance = loadBalance;
            this.httpClientFactory = httpClientFactory;
        }

        /// <summary>
        /// Get方法
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// param name="ServiceSchme">服務名稱:(http/https)</param>
        /// <param name="ServiceName">服務名稱</param>
        /// <param name="serviceLink">服務路徑</param>
        /// <returns></returns>
        public async Task<T> GetAsync<T>(string Serviceshcme, string ServiceName,string serviceLink)
        {
            // 1、獲取服務
            IList<ServiceUrl> serviceUrls = await serviceDiscovery.Discovery(ServiceName);

            // 2、負載均衡服務
            ServiceUrl serviceUrl = loadBalance.Select(serviceUrls);

            // 3、建立請求
            Console.WriteLine($"請求路徑:{Serviceshcme} +'://'+{serviceUrl.Url} + {serviceLink}");
            HttpClient httpClient = httpClientFactory.CreateClient("mrico");
            // HttpResponseMessage response = await httpClient.GetAsync(serviceUrl.Url + serviceLink);
            HttpResponseMessage response = await httpClient.GetAsync(Serviceshcme +"://"+serviceUrl.Url + serviceLink);

            // 3.1 json轉換成對象
            if (response.StatusCode == HttpStatusCode.OK)
            {
                string json = await response.Content.ReadAsStringAsync();

                return JsonConvert.DeserializeObject<T>(json);
            } else
            {
                // 3.2 進行自定義異常處理,這個地方進行了降級處理
                throw new Exception($"{ServiceName}服務調用錯誤:{response.Content.ReadAsStringAsync()}");
            }
        }

        /// <summary>
        /// Post方法
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// param name="ServiceSchme">服務名稱:(http/https)</param>
        /// <param name="ServiceName">服務名稱</param>
        /// <param name="serviceLink">服務路徑</param>
        /// <param name="paramData">服務參數</param>
        /// <returns></returns>
        public T Post<T>(string Serviceshcme, string ServiceName, string serviceLink, object paramData = null)
        {
            // 1、獲取服務
            IList<ServiceUrl> serviceUrls = serviceDiscovery.Discovery(ServiceName).Result;

            // 2、負載均衡服務
            ServiceUrl serviceUrl = loadBalance.Select(serviceUrls);

            // 3、建立請求
            Console.WriteLine($"請求路徑:{Serviceshcme} +'://'+{serviceUrl.Url} + {serviceLink}");
            HttpClient httpClient = httpClientFactory.CreateClient("mrico");

            // 3.1 轉換成json內容
            HttpContent hc = new StringContent(JsonConvert.SerializeObject(paramData), Encoding.UTF8, "application/json");

            // HttpResponseMessage response = await httpClient.GetAsync(serviceUrl.Url + serviceLink);
            HttpResponseMessage response = httpClient.PostAsync(Serviceshcme + "://" + serviceUrl.Url + serviceLink, hc).Result;

            // 3.1json轉換成對象
            if (response.StatusCode == HttpStatusCode.OK || response.StatusCode == HttpStatusCode.Created)
            {
                string json = response.Content.ReadAsStringAsync().Result;

                return JsonConvert.DeserializeObject<T>(json);
            }
            else
            {
                // 3.2、進行自定義異常處理,這個地方進行了降級處理
                throw new Exception($"{ServiceName}服務調用錯誤:{response.Content.ReadAsStringAsync()}");
            }
        }
    }
}
View Code
 
使用HttpContext來進行微服務通信

httpcontext:封裝有關單個HTTP請求的所有特定於HTTP的信息

里面有request、response、Connection 等

ASP.NET Core管道詳解[2]: HttpContext本質論

 

ABP中的動態C# API客戶端

要查看源碼看下是使用什么通信的

RPC框架通信:rpc、grpc

參考:

花了一個星期,我終於把RPC框架整明白了!

.NET Core 上的 gRPC

gRPC 官方文檔中文版

ASP.NET Core 使用 gRPC 初探 --老張的哲學

深入了解 gRPC:協議 

RPC(Remote Procedure Call):遠程過程調用,它是一種通過網絡從遠程計算機程序上請求服務,而不需要了解底層網絡技術的思想。

 

gRPC

gRpc是一個高性能、開源和通用的 RPC 框架,面向移動和 HTTP/2 設計。

gRPC 基於 HTTP/2 標准設計,帶來諸如雙向流、流控、頭部壓縮、單 TCP 連接上的多復用請求等特。這些特性使得其在移動設備上表現更好,更省電和節省空間占用。

異步消息通信

一般是 RabbitMQ 、Kafka

分層法

以文件分層法為主,以程序集分層法為次

架構說明:

  • 網關層:路由、限流、日志、監控、負載均衡、緩存等功能
    • 負載均衡:代理多個網關,做網關集群
    • oclet:
    • 熔斷降級:
    • 網關集群:
  • 認證授權層 IdentityServer4:
  • 聚合層:為頁面服務,處理頁面請求及給頁面提供數據。
  • 服務層:各種微服務,根據功能來拆分,例如訂單服務、商品服務、支付服務、認證服務等
  • 工具基礎層:服務發現、熔斷降級、日志、分布式事務、配置中心
    • 服務發現、注冊、配置 consul:客戶端發現模式、服務端發現模式、服務注冊表
    • 熔斷降級 Polly:
      • 熔斷:作用就是在特定的場景下關掉當前的通路,從而起到保護整個系統的效果
      • 降級:保證系統核心服務正常運行,暫停非核心的一些外圍服務
    • 分布式事務  Saga:保證同時操作多個服務時保持數據原子性
      • 原子性:如生成訂單時要同時扣減庫存,而訂單和商品庫存是兩個服務,使用分布式事務來保證兩個操作同時成功或同時失敗,避免數據不一致。
    • 消息隊列  CAP.RabbtMq:
    • 鏈路監控  SkyWalking:
    • 日志中心  Elasticsearch:
    • 數據庫:SQLServer、Mysql
    • 緩存
    • 對象映射器  AutoMapper
    • Web框架  AspNetCore
    • ORM   EntityFrameworkCore
    • 通信 HTTP:

 

微服務架構圖:

層次調用說明

先后順序:【網關層】(先Nginx后到網關)=》【聚合層】=》【微服務層】=》【數據層】

【核心層 / 基礎設施層】:沒有先后先后順序,因為其他服務都有都有項目引用 核心層,相當於它們的項目內都內已經包含了工具層,要用的時候直接調用就好

項目結構說明:

項目結構

  • AggregateService(聚合服務)
  • LocationService(位置服務)
  • MemberService(成員服務)
  • MicroService.Core(核心層 / 基礎設施層):只有它是類庫,其他服務都是控制台應用程序
  • MicroService.Gateway(網關服務)
  • MicroService.IdentityServer4(認證、授權服務)
  • MicroService.MVCClient(MVC客戶端)
  • MicroService.VideoService(視頻服務)
  • TeamService(團隊服務)

項目依賴

AggregateService 、TeamService、MicroService.VideoService都是依賴MicroService.Core

項目依賴與集群問題

主要區分清楚項目依賴和微服務之間的通訊就好:

  • MicroService.Core是類庫,項目依賴是類庫依賴,發布時會直接打包了依賴項目的相關文件
  • 微服務之間通訊是通過http或grpc的方式進行服務之間的通訊,相互之間沒有依賴

項目依賴的時候,在發布是會自動把依賴的項目打包進來,包括.dll、.exe、.pdb等文件,如下圖:

 

AggregateService(聚合服務)結構說明

 

TeamService(團隊服務)結構說明 

  • Controllers:控制器層 / 接口層(resful api)
    • 依賴Server層:構造函數注入時依賴,控制器的方法調用服務層server的方法
    • 依賴appsettings文件的ConsulRegistry配置:構造函數時依賴,在Starup類的Configure方法中有注入Consul相關配置
    • 依賴Models層
  • Models:領域模型層
    • 數據庫模型:數據庫根據它生產對應的表的字段、關系等
    • 視圖模型 / 領域模型:提供前端使用到的視圖模型 / 領域模型
  • Services:領域服務層(數據交互,包含業務邏輯)
    • 依賴倉儲層:構造函數注入時依賴
    • 增、刪、改、查方法,方法內只有調用倉儲層的方法
    • 為什么要服務層:
      • 重用:把不同服務的調用都在server層中完成
      • 擴展:如果控制器直接調用倉儲,有修改時可能會修改很多控制器很麻煩,有服務層把相同功能放在一起,修改也小
  • Repositories:領域倉儲層
    • 增、刪、改、查的方法,方法內有具體實現,沒有業務邏輯
    • 依賴數據庫上下文:構造函數注入時依賴
    • 方便更換數據庫

 

分布式事務omega

備注:omega文件夾下的4個類庫不需要手工創建,下載源碼中包含有,在項目中添加一個文件夾然后添加現有項目,然后在微服務層引用

  • Servicecomb.Saga.Omega.Abstractions:抽象層
  • Servicecomb.Saga.Omega.AspNetCore:AspNetCore層
  • Servicecomb.Saga.Omega.Core:核心層
  • Servicecomb.Saga.Omega.Protocol:協議層

測試Test

  • TeamService.Tests:團隊服務測試 

 

微服務之間通信

  • 每個服務器啟用時用Core層的UseConsulRegistry把自己服務根據服務名、地址注冊到consul中
  • 在Core層中的ConsulHttpClient類內已經把HttpClientIHttpClientFactoryHttpResponseMessage
  • 在聚合服務調用其他服務時,根據地址去調用,例如調用團隊服務器時是通過HttpTeamServiceClient中團隊地址是:https/TeamService//Teams

微服務如何拆分:

架構演進

  • 單體架構
  • 單數據庫多應用架構
  • 主從數據庫讀寫分離架構
  • 主從數據庫讀寫分離+緩存架構
  • 消息隊列架構
  • 面向服務(SOA)架構
  • 微服務架構

 

dapr


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM