做者:依樂祝
原文地址:http://www.javashuo.com/article/p-kejgcpxj-dv.htmlhtml
上篇《Ocelot簡易教程(二)之快速開始2》教你們如何快速跑起來一個ocelot實例項目,也只是簡單的對Ocelot進行了配置,這篇文章會給你們詳細的介紹一下Ocelot的配置信息。但願能對你們深刻使用Ocelot有所幫助。git
上篇中也提到了,最簡單的Ocelot以下面所示,只有簡單的兩個節點,一個是ReRoutes
,另外一個就是GlobalConfiguration
關於這兩個節點的做用,上篇也已經講述了,這裏再簡單的講下ReRoutes:告訴Ocelot如何處理上游的請求。GlobalConfiguration:顧名思義就是全局配置,此節點的配置容許覆蓋ReRoutes裏面的配置,你能夠在這裏進行通用的一些配置信息。github
{ "ReRoutes": [], "GlobalConfiguration": {} }
下面呢給出ReRoute 的全部的配置信息,固然在實際使用的時候你沒有必要所有進行配置,只須要根據你項目的實際須要進行相關的配置就能夠了。數據庫
"ReRoutes": [ { "DownstreamPathTemplate": "/api/{everything}",//下游路由模板 "UpstreamPathTemplate": "/good/{everything}",//上游路由模板 "UpstreamHttpMethod": [ "Get", "Post" ],//上游請求方法 "AddHeadersToRequest": {}, "UpstreamHeaderTransform": {}, "DownstreamHeaderTransform": {}, "AddClaimsToRequest": {}, "RouteClaimsRequirement": {}, "AddQueriesToRequest": {}, "RequestIdKey": null, "FileCacheOptions": { "TtlSeconds": 0, "Region": null }, "ReRouteIsCaseSensitive": false, "ServiceName": null, "DownstreamScheme": "http", "QoSOptions": {//Qos相關配置 "ExceptionsAllowedBeforeBreaking": 0, "DurationOfBreak": 0, "TimeoutValue": 0 }, "LoadBalancerOptions": {//負載均衡相關選項 "Type": "RoundRobin", "Key": null, "Expiry": 0 }, "RateLimitOptions": {//限流相關配置 "ClientWhitelist": [], "EnableRateLimiting": false, "Period": null, "PeriodTimespan": 0.0, "Limit": 0 }, "AuthenticationOptions": {//認證相關選項 "AuthenticationProviderKey": null, "AllowedScopes": [] }, "HttpHandlerOptions": {//HttpHandler相關的配置 "AllowAutoRedirect": false,//是否對下游重定向進行響應 "UseCookieContainer": false,//是否啓動CookieContainer儲存cookies "UseTracing": false, "UseProxy": true }, "DownstreamHostAndPorts": [//下游端口及host { "Host": "localhost", "Port": 1001 }, { "Host": "localhost", "Port": 1002 } ], "UpstreamHost": null,//上游Host "Key": null, "DelegatingHandlers": [], "Priority": 1, "Timeout": 0, "DangerousAcceptAnyServerCertificateValidator": false }
固然上面的配置項我就不一一的進行介紹,由於不少配置相信你們根據意思都能知道個大概了。我只會對比較經常使用的配置作下介紹。並且在接下來的文章中對對每一個節點進行單獨的詳細的介紹。在介紹以前呢先看Ocelot的幾個特性。json
這個特性容許用戶建立多個配置文件來方便的對大型項目進行配置。試想一下,若是你的項目有幾十個路由規則須要配置的話,那麼在一個配置文件進行配置應該很痛苦吧,有了這個特性後,你就能夠建立多個配置文件。Ocelot會自動合併他們。
在加載配置文件的時候 你能夠經過下面的方式來調用AddOcelot()方法來替換直接加載某個配置的寫法 如:AddJsonFile(「ocelot.json」)c#
.ConfigureAppConfiguration((hostingContext, config) => { config .SetBasePath(hostingContext.HostingEnvironment.ContentRootPath) .AddJsonFile("appsettings.json", true, true) .AddJsonFile($"appsettings.{hostingContext.HostingEnvironment.EnvironmentName}.json", true, true) .AddOcelot() .AddEnvironmentVariables(); })
在這種狀況下,Ocelot會尋找全部匹配了 (?i)ocelot.([a-zA-Z0-9]*).json
的文件,而後合併他們。如何你要設置GlobalConfiguration 屬性,那麼你須要創建一個ocelot.global.json 的文件來進行全局的配置。api
這裏上一個例子吧!能夠方便你們的理解。數組
新建一個ocelot.good.json文件,並加入下面的配置:緩存
{ "ReRoutes": [ { "DownstreamPathTemplate": "/api/{everything}", "DownstreamScheme": "http", "DownstreamHostAndPorts": [ { "Host": "localhost", "Port": 1001 }, { "Host": "localhost", "Port": 1002 } ], "UpstreamPathTemplate": "/good/{everything}", "UpstreamHttpMethod": [ "Get", "Post" ], "LoadBalancerOptions": { "Type": "RoundRobin" } } ] }
而後再新建一個ocelot.order.json文件,並加入下面的配置:服務器
{ "ReRoutes": [ { "DownstreamPathTemplate": "/api/{everything}", "DownstreamScheme": "http", "DownstreamHostAndPorts": [ { "Host": "localhost", "Port": 1001 }, { "Host": "localhost", "Port": 1002 } ], "UpstreamPathTemplate": "/order/{everything}", "UpstreamHttpMethod": [ "Get", "Post" ], "LoadBalancerOptions": { "Type": "RoundRobin" } } ] }
最後新建一個ocelot.all.json文件,並把上篇文章中的路由拷貝到裏面:
{ "ReRoutes": [ { "DownstreamPathTemplate": "/api/{everything}", "DownstreamScheme": "http", "DownstreamHostAndPorts": [ { "Host": "localhost", "Port": 1001 }, { "Host": "localhost", "Port": 1002 } ], "UpstreamPathTemplate": "/{everything}", "UpstreamHttpMethod": [ "Get", "Post" ], "LoadBalancerOptions": { "Type": "RoundRobin" } } ], "GlobalConfiguration": { } }
而後修改下,Program.cs文件中的代碼以下:
public static IWebHostBuilder CreateWebHostBuilder(string[] args) => WebHost.CreateDefaultBuilder(args) .ConfigureAppConfiguration((hostingContext, config) => { config .SetBasePath(hostingContext.HostingEnvironment.ContentRootPath) .AddJsonFile("appsettings.json", true, true) .AddJsonFile($"appsettings.{hostingContext.HostingEnvironment.EnvironmentName}.json", true, true) .AddOcelot() .AddEnvironmentVariables(); }) .UseUrls("http://localhost:1000") .UseStartup<Startup>();
這裏最重要的代碼就是config.AddOcelot()
了。這段代碼就會按照上面的規則查找全部符合條件的文件併合並路由。合併後的代碼以下:
{ "ReRoutes": [ { "DownstreamPathTemplate": "/api/{everything}", "UpstreamPathTemplate": "/{everything}", "UpstreamHttpMethod": [ "Get", "Post" ], "AddHeadersToRequest": {}, "UpstreamHeaderTransform": {}, "DownstreamHeaderTransform": {}, "AddClaimsToRequest": {}, "RouteClaimsRequirement": {}, "AddQueriesToRequest": {}, "RequestIdKey": null, "FileCacheOptions": { "TtlSeconds": 0, "Region": null }, "ReRouteIsCaseSensitive": false, "ServiceName": null, "DownstreamScheme": "http", "QoSOptions": { "ExceptionsAllowedBeforeBreaking": 0, "DurationOfBreak": 0, "TimeoutValue": 0 }, "LoadBalancerOptions": { "Type": "RoundRobin", "Key": null, "Expiry": 0 }, "RateLimitOptions": { "ClientWhitelist": [], "EnableRateLimiting": false, "Period": null, "PeriodTimespan": 0.0, "Limit": 0 }, "AuthenticationOptions": { "AuthenticationProviderKey": null, "AllowedScopes": [] }, "HttpHandlerOptions": { "AllowAutoRedirect": false, "UseCookieContainer": false, "UseTracing": false, "UseProxy": true }, "DownstreamHostAndPorts": [ { "Host": "localhost", "Port": 1001 }, { "Host": "localhost", "Port": 1002 } ], "UpstreamHost": null, "Key": null, "DelegatingHandlers": [], "Priority": 1, "Timeout": 0, "DangerousAcceptAnyServerCertificateValidator": false }, { "DownstreamPathTemplate": "/api/{everything}", "UpstreamPathTemplate": "/good/{everything}", "UpstreamHttpMethod": [ "Get", "Post" ], "AddHeadersToRequest": {}, "UpstreamHeaderTransform": {}, "DownstreamHeaderTransform": {}, "AddClaimsToRequest": {}, "RouteClaimsRequirement": {}, "AddQueriesToRequest": {}, "RequestIdKey": null, "FileCacheOptions": { "TtlSeconds": 0, "Region": null }, "ReRouteIsCaseSensitive": false, "ServiceName": null, "DownstreamScheme": "http", "QoSOptions": { "ExceptionsAllowedBeforeBreaking": 0, "DurationOfBreak": 0, "TimeoutValue": 0 }, "LoadBalancerOptions": { "Type": "RoundRobin", "Key": null, "Expiry": 0 }, "RateLimitOptions": { "ClientWhitelist": [], "EnableRateLimiting": false, "Period": null, "PeriodTimespan": 0.0, "Limit": 0 }, "AuthenticationOptions": { "AuthenticationProviderKey": null, "AllowedScopes": [] }, "HttpHandlerOptions": { "AllowAutoRedirect": false, "UseCookieContainer": false, "UseTracing": false, "UseProxy": true }, "DownstreamHostAndPorts": [ { "Host": "localhost", "Port": 1001 }, { "Host": "localhost", "Port": 1002 } ], "UpstreamHost": null, "Key": null, "DelegatingHandlers": [], "Priority": 1, "Timeout": 0, "DangerousAcceptAnyServerCertificateValidator": false }, { "DownstreamPathTemplate": "/api/{everything}", "UpstreamPathTemplate": "/order/{everything}", "UpstreamHttpMethod": [ "Get", "Post" ], "AddHeadersToRequest": {}, "UpstreamHeaderTransform": {}, "DownstreamHeaderTransform": {}, "AddClaimsToRequest": {}, "RouteClaimsRequirement": {}, "AddQueriesToRequest": {}, "RequestIdKey": null, "FileCacheOptions": { "TtlSeconds": 0, "Region": null }, "ReRouteIsCaseSensitive": false, "ServiceName": null, "DownstreamScheme": "http", "QoSOptions": { "ExceptionsAllowedBeforeBreaking": 0, "DurationOfBreak": 0, "TimeoutValue": 0 }, "LoadBalancerOptions": { "Type": "RoundRobin", "Key": null, "Expiry": 0 }, "RateLimitOptions": { "ClientWhitelist": [], "EnableRateLimiting": false, "Period": null, "PeriodTimespan": 0.0, "Limit": 0 }, "AuthenticationOptions": { "AuthenticationProviderKey": null, "AllowedScopes": [] }, "HttpHandlerOptions": { "AllowAutoRedirect": false, "UseCookieContainer": false, "UseTracing": false, "UseProxy": true }, "DownstreamHostAndPorts": [ { "Host": "localhost", "Port": 1001 }, { "Host": "localhost", "Port": 1002 } ], "UpstreamHost": null, "Key": null, "DelegatingHandlers": [], "Priority": 1, "Timeout": 0, "DangerousAcceptAnyServerCertificateValidator": false } ], "DynamicReRoutes": [], "Aggregates": [], "GlobalConfiguration": { "RequestIdKey": null, "ServiceDiscoveryProvider": { "Host": null, "Port": 0, "Type": null, "Token": null, "ConfigurationKey": null, "PollingInterval": 0 }, "RateLimitOptions": { "ClientIdHeader": "ClientId", "QuotaExceededMessage": null, "RateLimitCounterPrefix": "ocelot", "DisableRateLimitHeaders": false, "HttpStatusCode": 429 }, "QoSOptions": { "ExceptionsAllowedBeforeBreaking": 0, "DurationOfBreak": 0, "TimeoutValue": 0 }, "BaseUrl": null, "LoadBalancerOptions": { "Type": null, "Key": null, "Expiry": 0 }, "DownstreamScheme": null, "HttpHandlerOptions": { "AllowAutoRedirect": false, "UseCookieContainer": false, "UseTracing": false, "UseProxy": true } } }
Ocelot的合併方式是先對知足格式的文件遍歷查找,而後循環加載他們,並提取全部的ReRoutes以及AggregateReRoutes 的數據。若是發現ocelot.global.json ,則添加到GlobalConfiguration 中。而後Ocelto會將合併後的配置保存在ocelot.json的文件中,當Ocelot運行時會加載這個合併後的ocelot.json文件,從而加載了全部的配置。
注意:這裏須要注意的是Ocelot在合併的過程當中不會對內容進行驗證,只有在最終合併的配置進行校驗,因此若是發現問題的話,那麼你須要檢查最終生成的ocelot.json 是否出錯了!
這裏你首先要作的就是安裝Ocelot中提供的Consul的NuGet包,Nuget安裝方式:
Install-Package Ocelot.Provider.Consul
而後在註冊服務時添加以下內容:Ocelot將會嘗試在Consul KV存儲並加載配置。
services .AddOcelot() .AddConsul() .AddConfigStoredInConsul();
固然你還得把下面的配置添加到你的ocelot.json文件中。這裏定義Ocelot如何查找Consul根並從Consul中加載並存儲配置.
"GlobalConfiguration": { "ServiceDiscoveryProvider": { "Host": "localhost", "Port": 9500 } }
Ocelot支持在配置文件發生改變的時候從新加載json配置文件。在加載ocelot.json文件的時候按照下面進行配置,那麼當你手動更新ocelot.json文件時,Ocelot將從新加載ocelot.json配置文件。
config.AddJsonFile("ocelot.json", optional: false, reloadOnChange: true);
若是你使用Consul進行配置,你可能須要配置Key以便區分多個配置,爲了指定Key,你須要在json配置文件中的ServiceDiscoveryProvider部分設置ConfigurationKey屬性:
"GlobalConfiguration": { "ServiceDiscoveryProvider": { "Host": "localhost", "Port": 9500, "ConfigurationKey": "Oceolot_A" } }
在此實例中,Ocelot將會在Consul查找時使用Oceolot_A 做爲配置的Key.若是沒有設置ConfigurationKey 則Ocelot將使用字符串InternalConfiguration 做爲此配置的Key
在ReRoute配置中可使用HttpHandlerOptions來設置HttpHandler行爲:
若是你想忽略SSL 警告/錯誤,你能夠在你的ReRoute 配置中加上以下配置:
"DangerousAcceptAnyServerCertificateValidator": false
固然做者是不建議這樣作的,最好的方式是建立你本地以及遠程所信任的證書。
Ocelot的最主要的功能是接收傳入的http請求並將其轉發到下游服務。
Ocelot使用ReRoute節點描述將一個請求路由到另外一個請求。爲了讓路由在Ocelot中起做用,您須要在配置中設置ReRoute:
{ "ReRoutes": [ ] }
要配置ReRoute,您須要在ReRoutes json數組中至少添加一個:
{ "DownstreamPathTemplate": "/api/good/{goodId}",//下游路由模板 "DownstreamScheme": "http",//下游路由請求的方式 "DownstreamHostAndPorts": [//下游路由的Host以及端口 { "Host": "localhost", "Port": 1001, } ], "UpstreamPathTemplate": "/good/{goodId}",//上游路由請求的模板 "UpstreamHttpMethod": [ "Put", "Delete" ]//上游路由請求的方式 }
DownstreamPathTemplate,DownstreamScheme和DownstreamHostAndPorts定義請求將轉發到的URL。
DownstreamHostAndPorts是一個集合,用於定義您但願將請求轉發到的任何下游服務的主機和端口。一般這隻包含一個條目,但有時你但願對下游請求服務進行負載均衡,這個時候你就能夠添加多個條目,並配合負載均衡選項進行相關的負載均衡設置。
UpstreamPathTemplate是Ocelot用於標識要用於給定請求的DownstreamPathTemplate對應的URL。使用UpstreamHttpMethod以便Ocelot能夠區分具備不一樣HTTP謂詞的請求到相同的URL。您能夠設置特定的HTTP方法列表,也能夠設置一個空列表以容許全部的。
在Ocelot中,您能夠以{something}的形式將變量的佔位符添加到模板中。佔位符變量須要同時出如今DownstreamPathTemplate和UpstreamPathTemplate屬性中。請求時Ocelot將嘗試請求時進行替換。
你也能夠像下面這樣配置,捕獲全部的路由:
{ "DownstreamPathTemplate": "/api/{everything}", "DownstreamScheme": "http", "DownstreamHostAndPorts": [ { "Host": "localhost", "Port": 1001, }, { "Host": "localhost", "Port": 1002, } ], "UpstreamPathTemplate": "/{everything}", "UpstreamHttpMethod": [ "Get", "Post" ] }
這個配置將會把路徑+查詢字符串通通轉發到下游路由.
注意:默認的ReRouting的配置是不區分大小寫的,若是須要修改此配置,能夠經過下面進行配置:
"ReRouteIsCaseSensitive": true這意味着Ocelot將嘗試將傳入的上游URL與上游模板匹配時,區分大小寫。
Ocelot的路由還支持捕獲全部樣式路由,用戶能夠指定他們想要匹配全部請求。
若是您設置以下所示的配置,則全部請求都將直接代理。佔位符{url}名稱不重要,任何名稱均可以使用。
{ "DownstreamPathTemplate": "/{url}", "DownstreamScheme": "http", "DownstreamHostAndPorts": [ { "Host": "localhost", "Port": 1001, } ], "UpstreamPathTemplate": "/{url}", "UpstreamHttpMethod": [ "Get" ] }
上面配置的所有捕獲的優先級低於任何其餘法人ReRoute。若是您的配置中還有下面的ReRoute,那麼Ocelot會在所有捕獲以前匹配它。
{ "DownstreamPathTemplate": "/", "DownstreamScheme": "http", "DownstreamHostAndPorts": [ { "Host": "localhost", "Port": 1001, } ], "UpstreamPathTemplate": "/", "UpstreamHttpMethod": [ "Get" ] }
此功能容許您根據上游主機得到ReRoutes。這經過查看客戶端使用的主機頭,而後將其用做咱們用於識別ReRoute的信息的一部分來工做。
要使用此功能,請在配置中添加如下內容。
{ "DownstreamPathTemplate": "/", "DownstreamScheme": "http", "DownstreamHostAndPorts": [ { "Host": "localhost", "Port": 1001, } ], "UpstreamPathTemplate": "/", "UpstreamHttpMethod": [ "Get" ], "UpstreamHost": "yilezhu.cn" }
僅當主機標頭值爲yilezhu.cn時,纔會匹配上面的ReRoute。
若是您沒有在ReRoute上設置UpstreamHost,那麼任何主機頭都將與之匹配。這意味着若是你有兩個相同的ReRoutes,除了UpstreamHost,其中一個爲null而另外一個不爲null 那麼Ocelot將支持已設置的那個。
你能夠經過ocelot.json文件的ReRoutes節點中的Priorty屬性來設置匹配上游HttpRequest的優先級順序
好比,下面兩個路由:
{ "UpstreamPathTemplate": "/goods/{catchAll}" "Priority": 0 }
以及
{ "UpstreamPathTemplate": "/goods/delete" "Priority": 1 }
上面兩個路由中,若是向Ocelot發出的請求時/goods/delete
格式的話,則Ocelot會優先匹配/goods /delete
的路由。
做者的想法是在使用服務發現提供程序時啓用動態路由,這樣您就沒必要提供ReRoute的配置。咱們會在服務發現那一章進行詳細的介紹。
Ocelot容許您指定一個查詢字符串做爲DownstreamPathTemplate的一部分,以下例所示。
{ "ReRoutes": [ { "DownstreamPathTemplate": "/api/subscriptions/{subscriptionId}/updates?unitId={unitId}", "UpstreamPathTemplate": "/api/units/{subscriptionId}/{unitId}/updates", "UpstreamHttpMethod": [ "Get" ], "DownstreamScheme": "http", "DownstreamHostAndPorts": [ { "Host": "localhost", "Port": 50110 } ] } ], "GlobalConfiguration": { } }
在此示例中,Ocelot將使用上游路徑模板中{unitId}的值,並將其做爲名爲unitId的查詢字符串參數添加到下游請求中!
Ocelot還容許您將查詢字符串參數放在UpstreamPathTemplate中,以便您能夠將某些查詢與某些服務匹配。
{ "ReRoutes": [ { "DownstreamPathTemplate": "/api/units/{subscriptionId}/{unitId}/updates", "UpstreamPathTemplate": "/api/subscriptions/{subscriptionId}/updates?unitId={unitId}", "UpstreamHttpMethod": [ "Get" ], "DownstreamScheme": "http", "DownstreamHostAndPorts": [ { "Host": "localhost", "Port": 50110 } ] } ], "GlobalConfiguration": { } }
在此示例中,Ocelot將僅匹配具備匹配的url路徑的請求,而且查詢字符串以unitId = something開頭。您能夠在此以後進行其餘查詢,但必須以匹配參數開頭。此外,Ocelot將交換查詢字符串中的{unitId}參數,並在下游請求路徑中使用它。
固然是放上實例中的源碼地址了:https://github.com/yilezhu/OcelotDemo
本文主要是對Ocelot的新特性以及路由進行詳細的介紹,這些介紹對你使用ocelot會有很大的幫助。下篇文章呢,我會對請求聚合以及服務發現以及動態路由進行記錄,敬請期待!同時須要說明一點是,本文大部份內容是翻譯自官方文檔,固然中間穿插着本身在使用過程當中一些理解,但願你們可以喜歡!