.Net6 使用 Ocelot + Consul 看這篇就夠了

2023-01-31 18:01:24

前言

卯兔敲門,新的一年,祝大家前‘兔’似錦!希望大家假後還能找到公司的大門 O(∩_∩)O !
書接上文,我們使用了 Consul實現了服務註冊與發現,對Consul不熟悉的同學可以先看看。這篇文章我們來學習Ocelot閘道器,在這之前我們首先得需要知道「什麼是API閘道器?」,「為什麼要選擇Ocelot?」以及「如何將Consul與Ocelot結合起來」等等,同樣這些知識點網上的文章也介紹得比較詳細了,我這裡也只做簡單的介紹,然後本文只是個人學習與分享,不喜勿噴,謝謝。

什麼是API閘道器?

API閘道器是系統暴露在外部的一個存取入口。就像一個公司的門衛承擔著定址、限制進入、安全檢查、位置引導、等等功能。從物件導向設計的角度看,它與外觀模式類似。API閘道器封裝了系統內部架構,為每個使用者端提供一個客製化的API。它可能還具有其它職責,如身份驗證、監控、負載均衡、快取、請求分片與管理、靜態響應處理等等。API閘道器方式的核心要點是,所有的使用者端和消費端都通過統一的閘道器接入微服務,在閘道器層處理所有的非業務功能。通常,閘道器也是提供REST/HTTP的存取API。伺服器端通過API-GW註冊和管理服務。

Ocelot 介紹


Ocelot的開源地址:GitHub - ThreeMammals/Ocelot: .NET core API Gateway
Ocelot是一個用.NET Core實現並且開源的API閘道器,它功能強大,包括了:路由請求聚合服務發現認證鑑權限流熔斷、並內建了負載均衡器Service FabricButterfly Tracing整合。而且這些功能都只需要簡單的設定即可完成。

Ocelot工作流程

實際上Ocelot就是一系列按特定順序排列的中介軟體。

Ocelot首先通過設定將HttpRequest物件儲存到一個指定的狀態直到它到達用來建立HttpRequestMessage物件並將建立的HttpRequestMessage物件傳送到下游服務中的請求構造中介軟體。通過中介軟體來發出請求是Ocelot管道中做的最後一件事。它不會再呼叫下一個中介軟體。下游服務的響應會儲存在每個請求 scoped repository中,並作為一個請求返回到Ocelot管道中。有一箇中介軟體將HttpResponseMessage對映到HttpResponse物件並返回給使用者端。

基本上就是這樣,還有很多其他功能。

基本整合


想要了解更多資訊請移步官網 Big Picture — Ocelot 1.0.0 documentation

環境準備

.Net 6
Docker desktop
Visual Studio 2022
GitHub - fengzhonghao8-24/ConsulIntroduction

專案設定

在我們之前的Consul範例專案中新增一個WebApi專案Gateway

新增Ocelot的NuGet包

Program.cs 檔案中將Ocelot進行IOC注入,並替換我們原有的管道模型

增加Ocelot組態檔

這裡設定分為兩個部分。一組Routes和一個GlobalConfiguration。Routes是告訴 Ocelot 如何處理上游請求的物件。GlobalConfiguration全域性設定,允許覆蓋特定於路由的設定。如果您不想管理大量特定於路線的設定,這將很有用。

  • DownstreamPathTemplate:下游服務轉發地址模板
  • DownstreamScheme:下游服務http schema
  • DownstreamHostAndPorts:下游服務的地址,一般只會包含一個條目,如果想希望對下游服務的請求進行負載的話這裡可以填多項,同時選擇一個負載均衡器 LoadBalancerOptions
  • UpstreamPathTemplate: 上游也就是使用者輸入的請求Url模板
  • UpstreamHttpMethod: 上游請求http方法,可使用陣列

Program增加應用檔案設定
Ocelot 支援在更改時重新載入 json 組態檔。

builder.Configuration.AddJsonFile("ocelot.json", optional: false, reloadOnChange: true);

然後通過Gateway專案來存取我們上篇文章設定好的服務ServiceA

OK,成功存取,最基礎的設定就這麼簡單。
然後還有一些常用的設定

路由

萬能模板

此模板的優先順序低於任何其他 Route。如果你的設定中也有下面的 Route,那麼 Ocelot 會在 catch all 之前匹配它。

{
	"DownstreamPathTemplate":"/{url}",
	"DownstreamScheme":"https",
	"DownstreamHostAndPorts":[
		{
			"Host":"localhost",
			"Port":80,
		}
	],
	"UpstreamPathTemplate":"/{url}",
	"UpstreamHttpMethod":["Get"]
}

Prioirty優先順序

可以通過在 ocelot.json 中包含「優先順序」屬性來定義您希望路由與上游 HttpRequest 匹配的順序

{    
	"Priority": 0 
}

0 是最低優先順序,Ocelot 始終將 0 用於 /{catchAll} 路由,寫死設定

路由負載均衡

當下遊服務有多個節點的時候,我們可以在DownstreamHostAndPorts中進行設定。

LoadBalancerOptions將決定負載均衡的演演算法

  • LeastConnection – 將請求發往最空閒的那個伺服器
  • RoundRobin – 輪流傳送
  • NoLoadBalance – 總是發往第一個請求或者是服務發現

當然這裡只是作為範例演示,都只是寫死模式,實際情況我們需要動態的管理服務範例,所以最終會結合Consul來進行使用。

自定義負載均衡策略

當然也可以自定義負載均衡策略,實現ILoadBalancer介面然後根據抽象出來的下游節點資訊 Service來做自定義操作即可


這裡不做多概述,感興趣的同學可以參考原始碼自行實現。

其他

當然Ocelot還支援很多其他功能,感興趣的同學可以移步官網Big Picture — Ocelot 1.0.0 documentation

Consul + Ocelot

為什麼要將Consul與Ocelot結合使用?

在Ocelot已經支援簡單的負載功能,也就是當下遊服務存在多個結點的時候,Ocelot能夠承擔起負載均衡的作用。但是它不提供健康檢查,服務的註冊也只能通過手動在組態檔裡面新增完成。這不夠靈活並且在一定程度下會有風險。這個時候我們就可以用Consul來做服務發現,它能與Ocelot完美結合。

新增Consul設定

在我們 Geteway 專案中安裝 Ocelot.Provider.Consul Nuget包,然後在 Program.c 中增加IOC設定

然後在ocelot.json檔案中增加設定

  • UseServiceDiscovery:true – 使用服務發現
  • ServiceDiscoveryProvider – 服務發現的設定
  • LoadBalancerOptions – 負載方式
  • ServiceName – 註冊到Consul的服務名稱

如果Consul有叢集的話,ServiceDiscoveryProvider 這裡可以使用 例如 Nginx 地址來做設定。

檢查Consul

檢查Consul服務註冊情況,這裡我們就只為 ServiceA 啟動了兩個服務節點,方便測試負載。

啟動專案

第一次存取 - 埠5050

第二次存取 - 埠5051

到這裡,我們就差不多大功告成了。
然後這裡可能會遇到一些埠問題,導致通過閘道器存取不到服務,這裡不清楚的同學可以去了解下Docker的網路模式,這裡就不做多概述。

結尾

本文只是簡單的介紹了Ocelot的使用以及怎麼與Consul結合,後面還會繼續學習閘道器對接JWT或者IdentityServer4,然後還有Polly,感興趣的同學歡迎繼續關注!

程式碼倉庫地址

https://github.com/fengzhonghao8-24/Consul.Ocelot