Service Fabric 與 Ocelot 集成


概要

雲應用程序一般都須要使用前端網關,爲用戶、設備或其餘應用程序提供同一個入口點。 在 Service Fabric 中,網關能夠是任意無狀態服務(如 ASP.NET Core 應用程序) 。html

本文介紹瞭如何將Ocelot用做 Service Fabric 應用程序的網關。Ocelot直接與 Service Fabric 集成,以即可以使用一組豐富的路由規則向後端 Service Fabric 服務發佈 API。前端

架構git

常見 Service Fabric 體系結構使用單頁 Web 應用程序,向公開 HTTP API 的後端服務發出 HTTP 調用請求。github

clip_image002

隨着應用程序愈來愈複雜,必須向大量後端服務發佈API的網關亦是如此。Ocelot旨在經過路由規則、訪問控制、速率限制、監視、事件日誌記錄和響應緩存來處理複雜 API,最大限度地減小用戶須要執行的操做。 Ocelot支持 Service Fabric 服務發現、分區解析和副本選擇,從而智能地將請求直接路由到 Service Fabric 中的後端服務,用戶無需編寫本身的無狀態 API 網關。web

應用程序方案shell

Service Fabric 中的服務能夠是無狀態服務,也能夠是有狀態服務,可採用如下三種方案之一進行分區:單獨分區、Int64 範圍分區和已命名分區。 必須肯定特定服務實例的具體分區,才能解析服務終結點。解析服務終結點時,必須指定服務實例名稱(例如,fabric:/myapp/myservice)以及服務的具體分區,但單獨分區狀況除外。後端

Ocelot可與無狀態服務、有狀態服務和任何分區方案的任意組合配合使用。api

https://ocelot.readthedocs.io/en/latest/features/servicefabric.html緩存

若是您正在使用無狀態/Guest服務,則ocelot將可以經過命名服務進行代理而無需其餘任何操做。可是,若是您正在使用有狀態服務/ actor服務,則必須使用客戶端請求發送PartitionKind和PartitionKey查詢字符串值。安全

如下示例展現如何設置一個ReRoute以便在在Service Fabric中工做。 最重要的是ServiceName,它由Service Fabric應用程序名稱和特定服務名稱組成的。 咱們還須要將UseServiceDiscovery設置爲true,並在GlobalConfiguration中設置ServiceDiscoveryProvider。 這裏的例子顯示了一個典型的配置。 它假定Service Fabric在本地主機上運行,而且命名服務位於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 中內置的反向代理,Service Fabric 羣集中運行的微服務能夠發現包含 http 終結點的其餘服務,並與之通訊。

微服務通訊模型

Service Fabric 中的微服務在羣集中的部分節點上運行,能夠出於各類緣由在這些節點之間遷移。 所以,微服務的終結點可能會動態變化。 若要發現羣集中的其餘服務並與之通訊,微服務必須完成如下步驟:

l 經過命名服務解析服務位置。

l 鏈接到服務。

l 在實現服務解析以及在發生鏈接故障時應用的重試策略的循環中,包裝上述步驟

使用反向代理通訊

反向代理是在每一個節點上運行的服務,用於表明客戶端服務處理終結點解析、自動重試及其餘鏈接故障。 能夠將反向代理配置爲,一邊處理客戶端服務的請求,一邊應用各類策略。 藉助反向代理,客戶端服務可使用任意客戶端 HTTP 通訊庫,無需服務中有特殊的解析和重試邏輯。

反向代理在本地節點上公開一個或多個終結點,以供客戶端服務用來向其餘服務發送請求。

clip_image004

反向代理使用特定的統一資源標識符 (URI) 格式來識別傳入請求應該轉發到的服務分區:

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 轉發,在設置反向代理偵聽 HTTPS 後,請參閱使用反向代理鏈接到安全服務。

l 羣集的徹底限定域名 (FQDN) | 內部 IP: 對於外部客戶端,能夠配置反向代理,以即可以經過羣集域(例如 mycluster.eastus.cloudapp.azure.com)訪問反向代理。 默認狀況下,反向代理在每一個節點上運行。 對於內部流量,可在本地主機或任意內部節點 IP(例如 10.0.0.1)上訪問反向代理。

l Port:爲反向代理指定的端口,例如 19081。

l ServiceInstanceName: 在不使用「fabric:/」方案的狀況下嘗試訪問的已部署服務實例的徹底限定名稱。 例如,若要訪問 fabric:/myapp/myservice/ 服務,可使用 myapp/myservice。

l 服務實例名稱要區分大小寫。 若 URL 中的服務實例名稱大小寫不一樣,則會致使請求失敗,並顯示 404(未找到)。

l 後綴路徑: 要鏈接到的服務的實際 URL 路徑,例如 myapi/values/add/3。

l PartitionKey: 對於分區服務,這是針對要訪問的分區計算出的分區鍵。 請注意,這不是分區 ID GUID。 對於使用單獨分區方案的服務,此參數不是必需的。

l PartitionKind: 服務分區方案。 該方案能夠是「Int64Range」或「Named」。 對於使用單獨分區方案的服務,此參數不是必需的。

l ListenerName 服務中的終結點採用如下形式:{"Endpoints":{"Listener1":"Endpoint1","Listener2":"Endpoint2" ...}}。 當服務公開了多個終結點時,此參數標識應將客戶端請求轉發到的終結點。 若是服務只有一個偵聽器,則能夠省略此項。

l TargetReplicaSelector 這指定應當如何選擇目標副本或實例。

l 當目標服務爲有狀態服務時,TargetReplicaSelector 能夠是下列其中一項:「PrimaryReplica」、「RandomSecondaryReplica」或「RandomReplica」。 若是未指定此參數,默認值爲「PrimaryReplica」。

l 當目標服務爲無狀態服務時,反向代理將選擇服務分區的一個隨機實例來將實例轉發到其中。

l Timeout: 此參數指定反向代理針對服務建立的 HTTP 請求(表明客戶端請求)的超時。 默認值爲 60 秒。 這是一個可選參數

Ocelot充當微服務和外部客戶端之間的網絡邊界,能夠進行網絡地址轉換並將外部請求轉發到內部的 IP:端口終結點。 要容許外部客戶端直接訪問微服務的終結點,必須先將Ocelot配置爲將流量轉發到羣集中服務使用的每一個端口。 另外,大多數微服務(尤爲是有狀態微服務)並不駐留在羣集的全部節點上。 這些微服務在故障轉移時可在節點之間移動。 在這種狀況下,負載均衡器沒法有效肯定要將流量轉發到的副本的目標節點位置。

能夠在Ocelot中直接配置反向代理的端口,而無需配置單個服務的端口。 這種配置可以讓羣集外部的客戶端使用反向代理訪問羣集內部的服務,無需通過額外的配置。

clip_image006

經過Ocelot可從羣集外部訪問羣集中公開 HTTP 終結點的全部微服務。 這意味着微服務設計爲內部的可能會被肯定的惡意用戶發現。這潛在地提供可被利用的嚴重漏洞;例如:

惡意用戶能夠經過反覆調用沒有足夠強化的攻擊面的內部服務來發起拒絕服務攻擊。

惡意用戶可能會將格式錯誤的數據包傳送到內部服務,從而致使意外行爲。

設計爲內部的服務可能會返回不該公開給羣集外部的服務的私有或敏感信息,從而將此敏感信息泄露給惡意用戶。在網關上開啓身份認證、流控等措施來解決安全問題。

反向代理是一種可選的 Azure Service Fabric 服務,有助於在 Service Fabric 羣集中運行的微服務發現包含 http 終結點的其餘服務,並與之通訊,在建立新的 Service Fabric 羣集時,Azure 門戶提供了一個啓用反向代理的選項。 沒法經過門戶升級現有羣集來使用反向代理。

咱們的示例項目

咱們的示例項目代碼放在 https://github.com/geffzhang/NanoFabric-ServiceFabric ,解決方案中包含了一個後端服務ServiceA,是個無狀態的服務,一個Ocelot 網關和一個Identity Server 4的認證服務,在網關上集成了IdentityServer4 的認證服務 ,由網關負責認證,認證完成將Claims 轉換爲HttpHeader 中轉發到下游服務。

服務實例A是一個無狀態的服務

clip_image008

咱們將其配置爲運行2個實例。在Application Parameters中,我將* _InstanceCount參數值設置爲2:

clip_image010

讓Service Fabric選擇端口,咱們將從端點中刪除該Port屬性:

clip_image012

當開發機器上的沒法實如今同一端口上運行多個實例,若是填寫了Port 屬性,_InstanceCount只能保持爲1. 讓端口保持動態,咱們能夠在本地實現服務的伸縮。

部署本身的網關

部署本身的網關這聽起來像是須要作不少工做,實際上很是簡單。咱們須要與反向代理相同的行爲,只須要更多的控制。在咱們這個開源的開發的世界,這個問題已經解決了,咱們有開源的API網關Ocelot http://threemammals.com/ocelot ,並且作得很是好,能夠完美的和Service Fabric 一塊兒工做。

咱們將添加一個新的空aspnet core無狀態服務

clip_image014

讓咱們配置咱們的端點。您須要知道咱們的網關在哪裏,因此咱們給它一個特定的端口。在ServiceManifest中,設置端點的端口:

<Endpoint Protocol="http" Name="ServiceEndpoint" Type="Input" Port="8492" />

網關是系統的入口點,必須保持可用狀態。咱們在每一個節點上部署它。修改ApplicationParameters中添加的參數NanoFabricGateway_InstanceCount。確保生產部署的值爲-1。

<Parameter Name="NanoFabricGateway_InstanceCount" Value="-1"/>

請注意,若是部署到本地羣集,則沒法在同一端口上運行多個服務實例。對於本地開發羣集,要麼將其保留爲1,要麼讓端口爲動態。

代碼實現上並無什麼特殊的地方。

配置Azure負載均衡器

固然,沒有人想經過端口訪問您的網站8492。接下來,咱們須要設置負載均衡器以指向咱們新部署的網關。在部署在azure上的新集羣(能夠參考這篇文章使用Powershell https://noelbundick.com/posts/service-fabric-cluster-quickstart/ ),現有AppPortLBRule1端口80。編輯它,並將後端端口更改成指向網關端口:8492在個人狀況下。同時請注意,Load Balancer定義了一個Health Probe。若是健康檢測未成功,則負載均衡器將假定後端服務池不健康,而且不會重定向您的請求。

參考文章:

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

相關文章
相關標籤/搜索