Service Fabric 与Ocelot 的集成
概要
云應(yīng)用程序通常都需要使用前端網(wǎng)關(guān),為用戶、設(shè)備或其他應(yīng)用程序提供同一個入口點(diǎn)。 在 Service Fabric 中,網(wǎng)關(guān)可以是任意無狀態(tài)服務(wù)(如?ASP.NET Core 應(yīng)用程序) 。
本文介紹了如何將Ocelot用作 Service Fabric 應(yīng)用程序的網(wǎng)關(guān)。Ocelot直接與 Service Fabric 集成,以便可以使用一組豐富的路由規(guī)則向后端 Service Fabric 服務(wù)發(fā)布 API。
架構(gòu)
常見 Service Fabric 體系結(jié)構(gòu)使用單頁 Web 應(yīng)用程序,向公開 HTTP API 的后端服務(wù)發(fā)出 HTTP 調(diào)用請求。
隨著應(yīng)用程序越來越復(fù)雜,必須向大量后端服務(wù)發(fā)布API的網(wǎng)關(guān)亦是如此。Ocelot旨在通過路由規(guī)則、訪問控制、速率限制、監(jiān)視、事件日志記錄和響應(yīng)緩存來處理復(fù)雜 API,最大限度地減少用戶需要執(zhí)行的操作。 Ocelot支持 Service Fabric 服務(wù)發(fā)現(xiàn)、分區(qū)解析和副本選擇,從而智能地將請求直接路由到 Service Fabric 中的后端服務(wù),用戶無需編寫自己的無狀態(tài) API 網(wǎng)關(guān)。
應(yīng)用程序方案
Service Fabric 中的服務(wù)可以是無狀態(tài)服務(wù),也可以是有狀態(tài)服務(wù),可采用以下三種方案之一進(jìn)行分區(qū):單獨(dú)分區(qū)、Int64 范圍分區(qū)和已命名分區(qū)。 必須確定特定服務(wù)實(shí)例的具體分區(qū),才能解析服務(wù)終結(jié)點(diǎn)。解析服務(wù)終結(jié)點(diǎn)時(shí),必須指定服務(wù)實(shí)例名稱(例如,fabric:/myapp/myservice)以及服務(wù)的具體分區(qū),但單獨(dú)分區(qū)情況除外。
Ocelot可與無狀態(tài)服務(wù)、有狀態(tài)服務(wù)和任何分區(qū)方案的任意組合配合使用。
https://ocelot.readthedocs.io/en/latest/features/servicefabric.html
如果您正在使用無狀態(tài)/Guest服務(wù),則ocelot將能夠通過命名服務(wù)進(jìn)行代理而無需其他任何操作。但是,如果您正在使用有狀態(tài)服務(wù)/ actor服務(wù),則必須使用客戶端請求發(fā)送PartitionKind和PartitionKey查詢字符串值。
以下示例展示如何設(shè)置一個ReRoute以便在在Service Fabric中工作。 最重要的是ServiceName,它由Service Fabric應(yīng)用程序名稱和特定服務(wù)名稱組成的。 我們還需要將UseServiceDiscovery設(shè)置為true,并在GlobalConfiguration中設(shè)置ServiceDiscoveryProvider。 這里的例子顯示了一個典型的配置。 它假定Service Fabric在本地主機(jī)上運(yùn)行,并且命名服務(wù)位于19081端口上。
{
"ReRoutes": [
{
"DownstreamPathTemplate": "/api/values",
"UpstreamPathTemplate": "/servicea/api/values",
"UpstreamHttpMethod": [ "Get"],
"DownstreamScheme": "http",
"ServiceName": "NanoFabric_ServiceFabric/ServiceA",
"UseServiceDiscovery": true,
"AuthenticationOptions": {
"AuthenticationProviderKey": "apikey",
"AllowedScopes": []
},
"AddHeadersToRequest": {
"claims_City": "Claims[City] > value > |",
"claims_State": "Claims[State] > value > |"
},
"QoSOptions": {
"ExceptionsAllowedBeforeBreaking": 3,
"DurationOfBreak": 10,
"TimeoutValue": 5000
}
},
{
"DownstreamPathTemplate": "/{route}",
"UpstreamPathTemplate": "/serviceoauth/{route}",
"UpstreamHttpMethod": [ "Get", "Options", "Post" ],
"DownstreamScheme": "http",
"ServiceName": "NanoFabric_ServiceFabric/ServiceOAuth",
"UseServiceDiscovery": true
}
],
"GlobalConfiguration": {
"RequestIdKey": "OcRequestId",
"AdministrationPath": "/administration",
"ServiceDiscoveryProvider": {
"Host": "localhost",
"Port": 19081,
"Type": "ServiceFabric"
}
}
}
原理就是借助 Service Fabric 中內(nèi)置的反向代理,Service Fabric 群集中運(yùn)行的微服務(wù)可以發(fā)現(xiàn)包含 http 終結(jié)點(diǎn)的其他服務(wù),并與之通信。
微服務(wù)通信模型
Service Fabric 中的微服務(wù)在群集中的部分節(jié)點(diǎn)上運(yùn)行,可以出于各種原因在這些節(jié)點(diǎn)之間遷移。 因此,微服務(wù)的終結(jié)點(diǎn)可能會動態(tài)變化。 若要發(fā)現(xiàn)群集中的其他服務(wù)并與之通信,微服務(wù)必須完成以下步驟:
l 通過命名服務(wù)解析服務(wù)位置。
l 連接到服務(wù)。
l 在實(shí)現(xiàn)服務(wù)解析以及在發(fā)生連接故障時(shí)應(yīng)用的重試策略的循環(huán)中,包裝上述步驟
使用反向代理通信
反向代理是在每個節(jié)點(diǎn)上運(yùn)行的服務(wù),用于代表客戶端服務(wù)處理終結(jié)點(diǎn)解析、自動重試及其他連接故障。 可以將反向代理配置為,一邊處理客戶端服務(wù)的請求,一邊應(yīng)用各種策略。 借助反向代理,客戶端服務(wù)可以使用任意客戶端 HTTP 通信庫,無需服務(wù)中有特殊的解析和重試邏輯。
反向代理在本地節(jié)點(diǎn)上公開一個或多個終結(jié)點(diǎn),以供客戶端服務(wù)用來向其他服務(wù)發(fā)送請求。
反向代理使用特定的統(tǒng)一資源標(biāo)識符 (URI) 格式來識別傳入請求應(yīng)該轉(zhuǎn)發(fā)到的服務(wù)分區(qū):
http(s)://<Cluster FQDN | internal IP>:Port/<ServiceInstanceName>/<Suffix path>?PartitionKey=<key>&PartitionKind=<partitionkind>&ListenerName=<listenerName>&TargetReplicaSelector=<targetReplicaSelector>&Timeout=<timeout_in_seconds>
l http(s): 可以將反向代理配置為接受 HTTP 或 HTTPS 流量。 對于 HTTPS 轉(zhuǎn)發(fā),在設(shè)置反向代理偵聽 HTTPS 后,請參閱使用反向代理連接到安全服務(wù)。
l 群集的完全限定域名 (FQDN) | 內(nèi)部 IP: 對于外部客戶端,可以配置反向代理,以便可以通過群集域(例如 mycluster.eastus.cloudapp.azure.com)訪問反向代理。 默認(rèn)情況下,反向代理在每個節(jié)點(diǎn)上運(yùn)行。 對于內(nèi)部流量,可在本地主機(jī)或任意內(nèi)部節(jié)點(diǎn) IP(例如 10.0.0.1)上訪問反向代理。
l Port:為反向代理指定的端口,例如 19081。
l ServiceInstanceName: 在不使用“fabric:/”方案的情況下嘗試訪問的已部署服務(wù)實(shí)例的完全限定名稱。 例如,若要訪問 fabric:/myapp/myservice/ 服務(wù),可以使用 myapp/myservice。
l 服務(wù)實(shí)例名稱要區(qū)分大小寫。 若 URL 中的服務(wù)實(shí)例名稱大小寫不同,則會導(dǎo)致請求失敗,并顯示 404(未找到)。
l 后綴路徑: 要連接到的服務(wù)的實(shí)際 URL 路徑,例如 myapi/values/add/3。
l PartitionKey: 對于分區(qū)服務(wù),這是針對要訪問的分區(qū)計(jì)算出的分區(qū)鍵。 請注意,這不是分區(qū) ID GUID。 對于使用單獨(dú)分區(qū)方案的服務(wù),此參數(shù)不是必需的。
l PartitionKind: 服務(wù)分區(qū)方案。 該方案可以是“Int64Range”或“Named”。 對于使用單獨(dú)分區(qū)方案的服務(wù),此參數(shù)不是必需的。
l ListenerName 服務(wù)中的終結(jié)點(diǎn)采用以下形式:{"Endpoints":{"Listener1":"Endpoint1","Listener2":"Endpoint2" ...}}。 當(dāng)服務(wù)公開了多個終結(jié)點(diǎn)時(shí),此參數(shù)標(biāo)識應(yīng)將客戶端請求轉(zhuǎn)發(fā)到的終結(jié)點(diǎn)。 如果服務(wù)只有一個偵聽器,則可以省略此項(xiàng)。
l TargetReplicaSelector 這指定應(yīng)當(dāng)如何選擇目標(biāo)副本或?qū)嵗?/p>
l 當(dāng)目標(biāo)服務(wù)為有狀態(tài)服務(wù)時(shí),TargetReplicaSelector 可以是下列其中一項(xiàng):“PrimaryReplica”、“RandomSecondaryReplica”或“RandomReplica”。 如果未指定此參數(shù),默認(rèn)值為“PrimaryReplica”。
l 當(dāng)目標(biāo)服務(wù)為無狀態(tài)服務(wù)時(shí),反向代理將選擇服務(wù)分區(qū)的一個隨機(jī)實(shí)例來將實(shí)例轉(zhuǎn)發(fā)到其中。
l Timeout: 此參數(shù)指定反向代理針對服務(wù)創(chuàng)建的 HTTP 請求(代表客戶端請求)的超時(shí)。 默認(rèn)值為 60 秒。 這是一個可選參數(shù)
Ocelot充當(dāng)微服務(wù)和外部客戶端之間的網(wǎng)絡(luò)邊界,可以進(jìn)行網(wǎng)絡(luò)地址轉(zhuǎn)換并將外部請求轉(zhuǎn)發(fā)到內(nèi)部的 IP:端口終結(jié)點(diǎn)。 要允許外部客戶端直接訪問微服務(wù)的終結(jié)點(diǎn),必須先將Ocelot配置為將流量轉(zhuǎn)發(fā)到群集中服務(wù)使用的每個端口。 另外,大多數(shù)微服務(wù)(尤其是有狀態(tài)微服務(wù))并不駐留在群集的所有節(jié)點(diǎn)上。 這些微服務(wù)在故障轉(zhuǎn)移時(shí)可在節(jié)點(diǎn)之間移動。 在這種情況下,負(fù)載均衡器無法有效確定要將流量轉(zhuǎn)發(fā)到的副本的目標(biāo)節(jié)點(diǎn)位置。
可以在Ocelot中直接配置反向代理的端口,而無需配置單個服務(wù)的端口。 這種配置可讓群集外部的客戶端使用反向代理訪問群集內(nèi)部的服務(wù),無需經(jīng)過額外的配置。
通過Ocelot可從群集外部訪問群集中公開 HTTP 終結(jié)點(diǎn)的所有微服務(wù)。 這意味著微服務(wù)設(shè)計(jì)為內(nèi)部的可能會被確定的惡意用戶發(fā)現(xiàn)。這潛在地提供可被利用的嚴(yán)重漏洞;例如:
惡意用戶可以通過反復(fù)調(diào)用沒有足夠強(qiáng)化的攻擊面的內(nèi)部服務(wù)來發(fā)起拒絕服務(wù)攻擊。
惡意用戶可能會將格式錯誤的數(shù)據(jù)包傳送到內(nèi)部服務(wù),從而導(dǎo)致意外行為。
設(shè)計(jì)為內(nèi)部的服務(wù)可能會返回不應(yīng)公開給群集外部的服務(wù)的私有或敏感信息,從而將此敏感信息泄露給惡意用戶。在網(wǎng)關(guān)上開啟身份認(rèn)證、流控等措施來解決安全問題。
反向代理是一種可選的 Azure Service Fabric 服務(wù),有助于在 Service Fabric 群集中運(yùn)行的微服務(wù)發(fā)現(xiàn)包含 http 終結(jié)點(diǎn)的其他服務(wù),并與之通信,在創(chuàng)建新的 Service Fabric 群集時(shí),Azure 門戶提供了一個啟用反向代理的選項(xiàng)。 無法通過門戶升級現(xiàn)有群集來使用反向代理。
我們的示例項(xiàng)目
我們的示例項(xiàng)目代碼放在?https://github.com/geffzhang/NanoFabric-ServiceFabric?,解決方案中包含了一個后端服務(wù)ServiceA,是個無狀態(tài)的服務(wù),一個Ocelot 網(wǎng)關(guān)和一個Identity Server 4的認(rèn)證服務(wù),在網(wǎng)關(guān)上集成了IdentityServer4 的認(rèn)證服務(wù) ,由網(wǎng)關(guān)負(fù)責(zé)認(rèn)證,認(rèn)證完成將Claims 轉(zhuǎn)換為HttpHeader 中轉(zhuǎn)發(fā)到下游服務(wù)。
服務(wù)實(shí)例A是一個無狀態(tài)的服務(wù)
我們將其配置為運(yùn)行2個實(shí)例。在Application Parameters中,我將* _InstanceCount參數(shù)值設(shè)置為2:
讓Service Fabric選擇端口,我們將從端點(diǎn)中刪除該P(yáng)ort屬性:
當(dāng)開發(fā)機(jī)器上的無法實(shí)現(xiàn)在同一端口上運(yùn)行多個實(shí)例,如果填寫了Port 屬性,_InstanceCount只能保持為1. 讓端口保持動態(tài),我們可以在本地實(shí)現(xiàn)服務(wù)的伸縮。
部署自己的網(wǎng)關(guān)
部署自己的網(wǎng)關(guān)這聽起來像是需要做很多工作,實(shí)際上非常簡單。我們需要與反向代理相同的行為,只需要更多的控制。在我們這個開源的開發(fā)的世界,這個問題已經(jīng)解決了,我們有開源的API網(wǎng)關(guān)Ocelot?http://threemammals.com/ocelot?,而且做得非常好,可以完美的和Service Fabric 一起工作。
我們將添加一個新的空aspnet core無狀態(tài)服務(wù)
讓我們配置我們的端點(diǎn)。您需要知道我們的網(wǎng)關(guān)在哪里,所以我們給它一個特定的端口。在ServiceManifest中,設(shè)置端點(diǎn)的端口:
<Endpoint Protocol="http" Name="ServiceEndpoint" Type="Input" Port="8492" />
網(wǎng)關(guān)是系統(tǒng)的入口點(diǎn),必須保持可用狀態(tài)。我們在每個節(jié)點(diǎn)上部署它。修改ApplicationParameters中添加的參數(shù)NanoFabricGateway_InstanceCount。確保生產(chǎn)部署的值為-1。
<Parameter Name="NanoFabricGateway_InstanceCount" Value="-1"/>
請注意,如果部署到本地群集,則無法在同一端口上運(yùn)行多個服務(wù)實(shí)例。對于本地開發(fā)群集,要么將其保留為1,要么讓端口為動態(tài)。
代碼實(shí)現(xiàn)上并沒有什么特殊的地方。
配置Azure負(fù)載均衡器
當(dāng)然,沒有人想通過端口訪問您的網(wǎng)站8492。接下來,我們需要設(shè)置負(fù)載均衡器以指向我們新部署的網(wǎng)關(guān)。在部署在azure上的新集群(可以參考這篇文章使用Powershell?https://noelbundick.com/posts/service-fabric-cluster-quickstart/?),現(xiàn)有AppPortLBRule1端口80。編輯它,并將后端端口更改為指向網(wǎng)關(guān)端口:8492在我的情況下。同時(shí)請注意,Load Balancer定義了一個Health Probe。如果健康檢測未成功,則負(fù)載均衡器將假定后端服務(wù)池不健康,并且不會重定向您的請求。
參考文章:
https://docs.microsoft.com/zh-cn/azure/service-fabric/service-fabric-api-management-overview
https://blog.geist.no/azure-service-fabric-introduction-part-2-our-endpoint-a-webapi-based-stateless-service/
https://ocelot.readthedocs.io/en/latest/features/servicefabric.html
原文地址:https://www.cnblogs.com/shanyou/p/9645815.html
.NET社區(qū)新聞,深度好文,歡迎訪問公眾號文章匯總 http://www.csharpkit.com
總結(jié)
以上是生活随笔為你收集整理的Service Fabric 与Ocelot 的集成的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 积极参与开源项目,促进.NET Core
- 下一篇: .net core实践系列之短信服务-架