微服務實踐-快速搭建微服務架構

来源:https://www.cnblogs.com/OrcCoCo/archive/2022/08/26/16628343.html
-Advertisement-
Play Games

微服務說起來高大尚,實際擼一遍來試試看,用現在比較常用的微服務框架,Consul和Ocelote做一個Demo,一起來試試吧! 說在前面的話 準備好環境,拉取源代碼,按照每個章節中的【實踐操作】進行操作,即可搭建起來,已經測試通過。 不想把篇幅拉太長,且此文實踐為主,如果對微服務沒有理論基礎,建議先 ...


微服務說起來高大尚,實際擼一遍來試試看,用現在比較常用的微服務框架,Consul和Ocelote做一個Demo,一起來試試吧!

說在前面的話

準備好環境,拉取源代碼,按照每個章節中的【實踐操作】進行操作,即可搭建起來,已經測試通過。

不想把篇幅拉太長,且此文實踐為主,如果對微服務沒有理論基礎,建議先閱讀其他博主的微服務理論,再食用本文,效果更佳~

如有解釋不當或錯誤的地方,歡迎各位大佬加以斧正!
之後要是有空,後續會容器化部署上雲伺服器,把部署過程剪一個視頻出來。

環境準備(Windows版)

Windows單體部署架構圖

  • 用戶發送請求至網關地址,網關對此次請求做請求轉發,轉發的策略及配置規則在Ocelot項目中,指定一個configuration.json的配置文件,在宿主機創建IConfiguration時,將配置json文件作為鍵值對給Ocelot做配置使用

  • 一開始,用戶在授權中心獲取Token
  • 從ocelot源代碼可以看到FileRoute定義了Ocelot的基本配置
  • 上游的請求(upstream),在網關中,根據路由匹配規則(Routes),轉發到下游地址(downstream)
  • 下游地址便是服務地址,那網關如何知道將請求轉發到哪個服務呢,這裡便用上了Consul的服務註冊與發現,當然不僅僅只集成Consul,Consul只是選擇之一。
  • 請求在經過網關時,使用了Polly的彈性故障處理框架,加了一層自定義緩存。
  • 身份認證下放至服務實例,未在網關層加驗證

以上便是簡易的微服務Demo框架介紹,下邊開始拉取項目實踐吧!

服務註冊與發現

啟動並創建Consul集群

簡單來說,各個業務服務實例註冊在Consul這個平臺的節點中,各個節點分享註冊信息,一起組合成為一個集群。

每個節點分為客戶端模式與服務端模式,其區別就是,服務端會存儲各個節點的數據,客戶端則所有註冊到該節點的服務信息,都會轉發至其他服務端節點,本身不存儲這些信息。

也是由此原因,客戶端模式的節點數量是不限制的,服務端模式節點則會控制數據

raft是一種選舉的演算法,用來實現微服務CAP中的分散式一致性,上圖的Server模式帶星的則為選舉出來的Lead,可以自行瞭解一下

模擬動畫,輔助理解raft:http://thesecretlivesofdata.com/raft/
Consul配置詳解: https://www.cnblogs.com/sunsky303/p/9209024.html

實踐操作

準備Consul配置文件,源代碼根目錄下已經上傳

  • 啟動Consul有兩種方式,比如純命令行啟動、按照配置文件啟動
  • 因為是單機部署,所以此處為:配置文件指定了每個Consul實例的埠,按照配置文件結合命令進行啟動
// Windows 終端
 -- 進入Consul解壓目錄
 cd D:\Consul
 -- 服務端模式
.\consul.exe agent -server -bootstrap-expect=3 -data-dir=d:\consultmp\data-dir1 -config-file=D:\Consul\config\8500.json -node=server1 -bind='127.0.0.1' -client='0.0.0.0' -ui
.\consul.exe agent -server -data-dir=d:\consultmp\data-dir2 -config-file=D:\Consul\config\9500.json -node=server2 -bind='127.0.0.1' -client='0.0.0.0' -join='127.0.0.1:8301' -ui
.\consul.exe agent -server -data-dir=d:\consultmp\data-dir3 -config-file=D:\Consul\config\10500.json -node=server3 -bind='127.0.0.1' -client='0.0.0.0' -join='127.0.0.1:8301' -ui
 -- 客戶端模式
 .\consul.exe agent -data-dir=d:\consultmp\data-dir4 -config-file=D:\Consul\config\11500.json -node=client1 -bind='127.0.0.1' -join='127.0.0.1:8301' -client='0.0.0.0' -ui

下載Consul應用程式之後,存放在指定文件夾,分別啟動服務端模式和客戶端模式的節點,組成Consul集群

啟動集群之後可以分別打開
127.0.0.1:8500 127.0.0.1:9500 127.0.0.1:10500 127.0.0.1:11500
可以看到Consul的自帶的ui界面,啟動命令中的 -ui開啟此界面


至此,Consul集群搭建完成,接下來用Nginx為集群做請求負載均衡。

Nginx使用如下配置

worker_processes  1;

events {
    worker_connections  1024;
}


http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    keepalive_timeout  65;
	
	upstream ConsulNginx {
		server localhost:8500;
		server localhost:9500;
		server localhost:10500;
		server localhost:11500;
	}

    server {
        listen       8080;
        server_name  localhost;
		
        location / {
           proxy_pass http://ConsulNginx;
        }
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
    }
}

進入Nginx安裝目錄,使用start nginx命令

Nginx啟動成功,則進入http://localhost:8080/即可看到Consul的UI界面

業務服務啟動與註冊到Consul

準備一個業務服務程式,實際開發中可以為商品服務,訂單服務,支付服務等等,服務中在調用Consul提供的方法註冊在其節點中之後,業務服務需要拋出一個簡易的可以返回當前狀態的介面,用作健康檢查。

此Demo使用一個簡易的用戶服務做演示,其中包含了受保護的資源、可匿名訪問的資源,健康檢查則是一個列印當前日期的介面。

實踐操作

服務實例註冊到Consul節點中,Appsettings.json文件中的ConsulAddress對應註冊到某個Consul節點

// 啟動webapi
-- Windows 終端
 -- 進入指定文件夾,自行修改文件路徑,生成路徑
 cd D:\Study\micservice-master\MicServiceDemo\MicServiceWebApi\bin\Debug\netcoreapp3.1

 -- 微服務Api,可以是用戶服務,產品服務等待
 dotnet MicServiceWebApi.dll --urls="http://*:44380" --ip="127.0.0.1" --port=44380
 dotnet MicServiceWebApi.dll --urls="http://*:44381" --ip="127.0.0.1" --port=44381
 dotnet MicServiceWebApi.dll --urls="http://*:44382" --ip="127.0.0.1" --port=44382
 dotnet MicServiceWebApi.dll --urls="http://*:44383" --ip="127.0.0.1" --port=44383

註冊至服務Conul節點,當然可以直接用ConsulNginx 8080埠進行註冊,此處是為了註冊至每個節點而這樣處理

在此,啟動了四個服務實例:
127.0.0.1:44380 127.0.0.1:44381 127.0.0.2:44382 127.0.0.2:44383
分別註冊在4個consul節點之中
http://127.0.0.1:8500 http://127.0.0.1:9500 http://127.0.0.1:10500 http://127.0.0.1:11500

試著請求 127.0.0.1:44380/api/user/getall 請求保護資源,因為未授權則會是401無許可權錯誤,這裡需要授權中心拿到accesstoken才可以獲取到結果,Token的獲取在下一節便能知道。
接著嘗試請求127.0.0.1:44381/api/user/getallwithnoverify 請求匿名介面,則可以拿到mock的數據。

授權中心

目前為止,此時還只是註冊了服務,獲取數據還是請求的業務服務暴露出來的地址與埠,這顯然還不算微服務,也不安全,現在先把授權中心啟動,待萬事具備,再網關啟動則可以跑通整個鏈路。
當然為了安全,服務實例部署到雲伺服器,會將44380這些埠用防火牆給牆柱,不讓外部直接訪問,只留下網關埠地址即可

Ids4授權中心

Identity Server 4 中有多種授權模式,常見的密碼模式、客戶端模式用的比較多,這裡使用簡單的客戶端模式,他們都是基於Oauth2.0協議,可自行瞭解,這裡不展開,使用起來還是很容易理解。

AuthenticationCenter項目,Startup中啟用的授權中心services.AddIdentityServer,就是核心的一些配置和參數,他們決定了授權服務保護了哪些API作用域,決定了哪些客戶端可以使用這個授權服務。


這裡指定了一個客戶端的Id與密碼,以及授權訪問的域

StartUp.cs授權下方的【測試訪問受保護資源】,則是在授權中心這個項目中做了一個測試,用於測試授權訪問是否成功,例如:
Home/Index 設為[Authorize] 需要授權才能訪問
Home/Allow 設為[AllowAnonymous] 匿名訪問

實踐操作

// 啟動授權中心

 -- 進入生成目錄
 cd G:\Study\Git\micservice\MicServiceDemo\AuthenticationCenter\bin\Debug\netcoreapp3.1\
 -- 啟動授權中心
 dotnet AuthenticationCenter.dll --urls="http://*:7000" --ip="127.0.0.1" --port=7000

驗證授權中心是否生效,此時預留測試介面派上用場
1.從授權中心獲取token,http://localhost:7000/connect/token

  1. 直接訪問受保護的資源,必定401無權訪問,將獲取的token放置請求頭中,即可通過授權

授權中心,便啟動測試成功了,以上的測試是一個極簡的OAuth2.0流程,授權中心拿Token去訪問受保護資源

網關啟動

現在服務註冊準備好了,多個業務服務也註冊在Consul的各個節點之中,授權中心也是啟動可授權狀態,現在便開始Ocelot網關的啟動

Ocelot

在上文中一起看過源碼,瞭解到ocelot集成了包括路由、請求聚合、服務發現、認證鑒權、限流、負載均衡等功能。而這些功能都可以直接通過修改json配置文件即可使用

//*****************************超時+限流+熔斷+降級+Consul+Polly********************************
{
  "Routes": [
    {
      //轉發到下游服務地址--url變數
      "DownstreamPathTemplate": "/api/{url}", // 服務地址--url變數
      //下游http協議
      "DownstreamScheme": "http",
      //負載方式,
      "LoadBalancerOptions": {
        "Type": "RoundRobin" // RoundRobin 輪詢 LeastConnection-最少連接數的伺服器   NoLoadBalance不負載均衡
      },
      //上游地址
      "UpstreamPathTemplate": "/gateway/{url}", // 網關地址--url變數 // 衝突的還可以加權重Priority
      "UpstreamHttpMethod": [ "Get", "Post", "DELETE", "PUT" ],
      // 使用服務發現
      "UseServiceDiscovery": true,
      "ServiceName": "MicServiceDemo", //consul服務名稱
      // 限流設置, polly
      "RateLimitOptions": {
        "ClientWhitelist": [ "admin" ], //白名單 請求頭ClientId 區分大小寫
        "EnableRateLimiting": true,
        "Period": "5m", //1s, 5m, 1h, 1d
        "PeriodTimespan": 30, //多少秒之後客戶端可以重試
        "Limit": 5 //統計時間段內允許的最大請求數量
      },
      // 熔斷設置,熔斷器使用Polly
      //"QoSOptions": {
      //  "ExceptionsAllowedBeforeBreaking": 3, //允許多少個異常請求
      //  "DurationOfBreak": 10000, // 熔斷的時間,單位為ms
      //  "TimeoutValue": 2000 //單位ms 如果下游請求的處理時間超過多少則自如將請求設置為超時 預設90秒
      //}
      // 鑒權
      //"AuthenticationOptions": {
      //  "AuthenticationProviderKey": "UserGatewayKey", // 指定一個key,startUp中使用
      //  "AllowedScopes": [ "gatewayScope" ]
      //},

      // 文件緩存
      "FileCacheOptions": {
        "TtlSeconds": 15,
        "Region": "UserCache" //可以調用Api清理
      }
    }
  ],
  "GlobalConfiguration": {
    "ServiceDiscoveryProvider": {
      "Host": "localhost",  // Consul 集群地址
      "Port": 8080, // Consul Nginx負載均衡 埠
      // "Port": 8500. // Consul 節點埠
      // 由Consul提供服務發現
      "Type": "Consul"
    },

    // 限流選項
    "RateLimitOptions": {
      "QuotaExceededMessage": "請求太頻繁,觸發限流 ", // 當請求過載被截斷時返回的消息
      "HttpStatusCode": 666 // 當請求過載被截斷時返回的http status
      //"ClientIdHeader": "client_id" // 用來識別客戶端的請求頭,預設是 ClientId
    }
  }
}

在此配置下,可以大致瞭解,請求經過網關時,Ocelot所做的一些處理

  • 上游當請求至網關,符合 UpstreamPathTemplate節點所設置的模板“/gateway/{url}”,則將請求下發至下游的DownstreamPathTemplate:"/api/{url}"
  • 服務的提供者則為GlobalConfiguration.ServiceDiscoveryProvider,包含Consul的地址與埠,服務名稱為"ServiceName": "MicServiceDemo"
  • 判斷該請求是否觸發polly的限流策略,在此配置中RateLimitOptionsGlobalConfiguration.RateLimitOptions的策略為:5分鐘之內,至多請求5次,第6次開始HTTP狀態碼為666,返回的信息為“請求太頻繁,觸發限流”,30秒冷卻期,請求頭中加入 ClientId=admin,則為白名單可不受限流策略影響
  • 授權策略在這裡註釋了,認證授權在服務層做,而不再網關層,如果想要在網關進行授權認證,取消註釋即可

實踐操作

 -- 進入生成目錄
 cd D:\Study\Git\micservice\MicServiceDemo\OcelotGateway\bin\Debug\netcoreapp3.1\
 -- Windows 終端
 dotnet OcelotGateway.dll --urls="http://*:6297" --ip="127.0.0.1" --port=6297
 dotnet OcelotGateway.dll --urls="http://*:6298" --ip="127.0.0.1" --port=6298
 dotnet OcelotGateway.dll --urls="http://*:6299" --ip="127.0.0.1" --port=6299

為了容錯及高可用, 啟動三個 網關實例。
此時可以用 http://localhost:6297/gateway/user/getallwithnoverify測試鏈路是否通了

  • http://localhost:6297/gateway/user/getallwithnoverify符合網關下發請求的規則,則在服務註冊中心(NginxForConsul:localhost:8080)取一個節點(此處隨機到節點client1)
  • 將請求下發至http://client1:44380/api/user/getallwithnoverify
  • 因為修改了Host文件,client1映射為127.0.0.1,故請求轉發的真實地址為http://127.0.0.1:44380/api/user/getallwithnoverify
    至此網關的集群搭建已完成,與Consul集群一樣,這裡再用Nginx做一層針對於Ocelot網關的負載均衡

NginxForOcelot 使用如下配置

worker_processes  1;

events {
    worker_connections  1024;
}


http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    keepalive_timeout  65;

	upstream OcelotNginx {
		server localhost:6297;
		server localhost:6298;
		server localhost:6299;
	}

    server {
        listen       9090;
        server_name  localhost;

        location / {
            proxy_pass http://OcelotNginx;
        }

        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
    }
}

進入Nginx安裝目錄,使用start nginx命令


啟動Nginx之後,則可在上文的基礎上再做一次負載均衡。
嘗試請求 http://127.0.0.1:9090/gateway/user/getallwithnoverify,則會自動選擇Ocelot集群中的某一個網關進行請求下發

OK,至此整個微服務架構就搭建完了,下麵進行測試

測試負載均衡


多次請求網關獲取數據,返回的apiDomain不盡相同,則負載均衡完成
當然可以查看Ocelot網關的控制台,是將請求轉發至哪個網關,及其網關下的Consul節點

測試授權訪問


直接訪問http://localhost:9090/gateway/User/GetAll是為401未授權錯誤。
在授權中心獲取Token之後,ApiPost中填入認證Token,即可獲取到受保護介面提供的數據

測試限流


快速請求多次,觸發限流

總結

這次的微服務搭建,只在單機環境下,做的負載均衡都是偽負載均衡,沒有整虛擬機和多個伺服器上去部署,確實是一個遺憾,但是涉及的方面比較多還是有很多的學習價值,Consul和Ocelot這一套算是很常見的.net 微服務框架了,之後也可以試試其他框架。

往後,準備給目前這一套架構舔磚加瓦,比如分散式配置中心Apollo,分散式系統的應用程式性能監視工具 skywalking等等.....

最後再貼一下架構圖

總結一下部署的流程

  • 啟動Consul集群
  • 為Consul集群添加Nginx 負載均衡
  • 啟動服務實例,並且註冊至Consul
  • 啟動Ids4授權中心
  • 啟動Ocelot網關集群
  • 為網關集群添加Nginx 負載均衡

源代碼

【Gitee】源代碼 https://gitee.com/yi_zihao/micservice
【GitHub】源代碼 https://github.com/OrzCoCo-Y/MicService.Net.git

參考資料

【博客園-可均可可】微服務簡介與技術棧 https://www.cnblogs.com/PatrickLiu/p/13925259.html
【博客園-sunsky303】consul配置參數大全、詳解、總結 https://www.cnblogs.com/sunsky303/p/9209024.html
【博客園-神游虛空】Ocelot 發現服務總是失敗的解決辦法 https://www.cnblogs.com/citycomputing/p/12070909.html
【raft】 http://thesecretlivesofdata.com/raft/


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

-Advertisement-
Play Games
更多相關文章
  • <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="wi ...
  • JavaScript函數 1.函數的語法格式 function 函數名(形參1,形參2,形參3....){ // 函數註釋,解釋說明該函數用來做什麼 函數體代碼 return 返回值 } 2.無參函數 function func1(){ console.log('hello world') } fu ...
  • 如何在 IconFont 上獲取圖標資源 阿裡巴巴矢量圖標庫網站(https://www.iconfont.cn/)上提供了非常豐富的圖標資源,包括 SVG、AI、PNG、字體圖標等格式。使用該網站提供的圖標,需要在該網站上註冊賬號並登錄。 1 搜索圖標 登錄成功後,在首頁的搜索框中搜索關鍵字,例如 ...
  • 千分位格式化 在項目中經常碰到關於貨幣金額的頁面顯示,為了讓金額的顯示更為人性化與規範化,需要加入貨幣格式化策略。也就是所謂的數字千分位格式化。 例如 123456789 => 123,456,789 、 123456789.123 => 123,456,789.123 const formatMo ...
  • 根據`業務功能`進行模塊化一直以來都是後端的普遍做法,而Web前端則通常都是按照UI界面的視圖區塊`View`來進行模塊化,這樣的模塊實際上只是`Component組件`,不具備獨立自治的能力。究其原因我想是因為在早期Web1.0的時代,前端的職能就是僅僅作為後端API數據的一個Render渲染器,... ...
  • 首先MDN官網中有一句寫道: assign()語法: Object.assign(target, ...sources) target:目標對象,接收源對象屬性的對象,也是修改後的返回值。sources:源對象,包含將被合併的屬性。下麵來看例子: let s = { a: 1 } let targe ...
  • Sass提供了許多內置模塊,其中包含有用的函數(以及mixin)。這些模塊可以像任何用戶定義的樣式表一樣使用@use規則載入,它們的函數可以像任何其他模塊成員一樣調用。所有內置模塊URL都以sass開頭:表示它們是sass本身的一部分。 常見函數簡介,更多函數列表可看:https://sass-la ...
  • 引言 領域驅動設計並不是新的架構設計理論,從Eric Evans提出至今已經有十多年曆史。由於微服務架構的興起,DDD常用於指導微服務邊界劃分,並重新廣泛進入軟體研發大眾的視野。DDD的理念及應用普及在國外相對成熟,在國內尚處於初期發展階段。國內的很多社區以及企業組織內部近幾年對於DDD的探討和應用 ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...