配置有两个部分。 一组ReRoutes
和一个GlobalConfiguration
。 ReRoutes
是告诉Ocelot
如何处理上游请求的对象。Globalconfiguration
有些奇特,可以覆盖ReRoute
节点的特殊设置。 如果您不想管理大量ReRoute
特定设置,这将非常有用。
{
"ReRoutes": [],
"GlobalConfiguration": {}
}
这是一个ReRoute
配置示例,你不需要全部都设置,但这是目前可用的所有设置:
{
"DownstreamPathTemplate": "/",
"UpstreamPathTemplate": "/",
"UpstreamHttpMethod": [
"Get"
],
"AddHeadersToRequest": {},
"AddClaimsToRequest": {},
"RouteClaimsRequirement": {},
"AddQueriesToRequest": {},
"RequestIdKey": "",
"FileCacheOptions": {
"TtlSeconds": 0,
"Region": ""
},
"ReRouteIsCaseSensitive": false,
"ServiceName": "",
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [
{
"Host": "localhost",
"Port": 51876,
}
],
"QoSOptions": {
"ExceptionsAllowedBeforeBreaking": 0,
"DurationOfBreak": 0,
"TimeoutValue": 0
},
"LoadBalancer": "",
"RateLimitOptions": {
"ClientWhitelist": [],
"EnableRateLimiting": false,
"Period": "",
"PeriodTimespan": 0,
"Limit": 0
},
"AuthenticationOptions": {
"AuthenticationProviderKey": "",
"AllowedScopes": []
},
"HttpHandlerOptions": {
"AllowAutoRedirect": true,
"UseCookieContainer": true,
"UseTracing": true
},
"DangerousAcceptAnyServerCertificateValidator": false
}
完全示例
{
"ReRoutes": [
{
"DownstreamPathTemplate": "/profile",
"DownstreamScheme": "http",
"UpstreamPathTemplate": "/profile",
"UpstreamHttpMethod": [ "Get" ],
"DownstreamHostAndPorts": [
{
"Host": "localhost",
"Port": 5001
}
],
"QoSOptions": {
"TimeoutValue": 360000
}
},
{
"DownstreamPathTemplate": "/api/v1/todo/",
"DownstreamScheme": "http",
"UpstreamPathTemplate": "/api/v1/todo/",
"UpstreamHttpMethod": [ "Get", "Post" ],
"DownstreamHostAndPorts": [
{
"Host": "lxtodo.azurewebsites.net",
"Port": 80
}
],
"DownstreamHeaderTransform": {
"Location": "{DownstreamBaseUrl}, {BaseUrl}"
}
},
{
"DownstreamPathTemplate": "/api/values",
"DownstreamScheme": "https",
"UpstreamPathTemplate": "/api/values",
"UpstreamHttpMethod": [ "Get" ],
"DownstreamHostAndPorts": [
{
"Host": "testapivalues.azurewebsites.net",
"Port": 443
}
]
},
{
"DownstreamPathTemplate": "/",
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [
{
"Host": "localhost",
"Port": 52876
}
],
"UpstreamPathTemplate": "/identityserverexample",
"UpstreamHttpMethod": [ "Get" ],
"QoSOptions": {
"ExceptionsAllowedBeforeBreaking": 3,
"DurationOfBreak": 10,
"TimeoutValue": 5000
},
"AuthenticationOptions": {
"AuthenticationProviderKey": "TestKey",
"AllowedScopes": [
"openid",
"offline_access"
]
},
"AddHeadersToRequest": {
"CustomerId": "Claims[CustomerId] > value",
"LocationId": "Claims[LocationId] > value",
"UserType": "Claims[sub] > value[0] > |",
"UserId": "Claims[sub] > value[1] > |"
},
"AddClaimsToRequest": {
"CustomerId": "Claims[CustomerId] > value",
"LocationId": "Claims[LocationId] > value",
"UserType": "Claims[sub] > value[0] > |",
"UserId": "Claims[sub] > value[1] > |"
},
"AddQueriesToRequest": {
"CustomerId": "Claims[CustomerId] > value",
"LocationId": "Claims[LocationId] > value",
"UserType": "Claims[sub] > value[0] > |",
"UserId": "Claims[sub] > value[1] > |"
},
"RouteClaimsRequirement": {
"UserType": "registered"
},
"RequestIdKey": "OcRequestId"
},
{
"DownstreamPathTemplate": "/posts",
"DownstreamScheme": "https",
"DownstreamHostAndPorts": [
{
"Host": "jsonplaceholder.typicode.com",
"Port": 443
}
],
"UpstreamPathTemplate": "/posts",
"UpstreamHttpMethod": [ "Get" ],
"HttpHandlerOptions": {
"AllowAutoRedirect": true,
"UseCookieContainer": true
},
"QoSOptions": {
"ExceptionsAllowedBeforeBreaking": 3,
"DurationOfBreak": 10,
"TimeoutValue": 5000
}
},
{
"DownstreamPathTemplate": "/posts/{postId}",
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [
{
"Host": "jsonplaceholder.typicode.com",
"Port": 80
}
],
"UpstreamPathTemplate": "/posts/{postId}",
"UpstreamHttpMethod": [ "Get" ],
"RequestIdKey": "ReRouteRequestId",
"HttpHandlerOptions": {
"AllowAutoRedirect": true,
"UseCookieContainer": true,
"UseTracing": true,
"UseProxy": true
},
"QoSOptions": {
"ExceptionsAllowedBeforeBreaking": 3,
"DurationOfBreak": 10,
"TimeoutValue": 5000
}
},
{
"DownstreamPathTemplate": "/posts/{postId}/comments",
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [
{
"Host": "jsonplaceholder.typicode.com",
"Port": 80
}
],
"UpstreamPathTemplate": "/posts/{postId}/comments",
"UpstreamHttpMethod": [ "Get" ],
"HttpHandlerOptions": {
"AllowAutoRedirect": true,
"UseCookieContainer": true,
"UseTracing": false
},
"QoSOptions": {
"ExceptionsAllowedBeforeBreaking": 3,
"DurationOfBreak": 10,
"TimeoutValue": 5000
}
},
{
"DownstreamPathTemplate": "/comments",
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [
{
"Host": "jsonplaceholder.typicode.com",
"Port": 80
}
],
"UpstreamPathTemplate": "/comments",
"UpstreamHttpMethod": [ "Get" ],
"QoSOptions": {
"ExceptionsAllowedBeforeBreaking": 3,
"DurationOfBreak": 10,
"TimeoutValue": 5000
}
},
{
"DownstreamPathTemplate": "/posts",
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [
{
"Host": "jsonplaceholder.typicode.com",
"Port": 80
}
],
"UpstreamPathTemplate": "/posts",
"UpstreamHttpMethod": [ "Post" ],
"QoSOptions": {
"ExceptionsAllowedBeforeBreaking": 3,
"DurationOfBreak": 10,
"TimeoutValue": 5000
}
},
{
"DownstreamPathTemplate": "/posts/{postId}",
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [
{
"Host": "jsonplaceholder.typicode.com",
"Port": 80
}
],
"UpstreamPathTemplate": "/posts/{postId}",
"UpstreamHttpMethod": [ "Put" ],
"QoSOptions": {
"ExceptionsAllowedBeforeBreaking": 3,
"DurationOfBreak": 10,
"TimeoutValue": 5000
}
},
{
"DownstreamPathTemplate": "/posts/{postId}",
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [
{
"Host": "jsonplaceholder.typicode.com",
"Port": 80
}
],
"UpstreamPathTemplate": "/posts/{postId}",
"UpstreamHttpMethod": [ "Patch" ],
"QoSOptions": {
"ExceptionsAllowedBeforeBreaking": 3,
"DurationOfBreak": 10,
"TimeoutValue": 5000
}
},
{
"DownstreamPathTemplate": "/posts/{postId}",
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [
{
"Host": "jsonplaceholder.typicode.com",
"Port": 80
}
],
"UpstreamPathTemplate": "/posts/{postId}",
"UpstreamHttpMethod": [ "Delete" ],
"QoSOptions": {
"ExceptionsAllowedBeforeBreaking": 3,
"DurationOfBreak": 10,
"TimeoutValue": 5000
}
},
{
"DownstreamPathTemplate": "/api/products",
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [
{
"Host": "jsonplaceholder.typicode.com",
"Port": 80
}
],
"UpstreamPathTemplate": "/products",
"UpstreamHttpMethod": [ "Get" ],
"QoSOptions": {
"ExceptionsAllowedBeforeBreaking": 3,
"DurationOfBreak": 10,
"TimeoutValue": 5000
},
"FileCacheOptions": { "TtlSeconds": 15 }
},
{
"DownstreamPathTemplate": "/api/products/{productId}",
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [
{
"Host": "jsonplaceholder.typicode.com",
"Port": 80
}
],
"UpstreamPathTemplate": "/products/{productId}",
"UpstreamHttpMethod": [ "Get" ],
"FileCacheOptions": { "TtlSeconds": 15 }
},
{
"DownstreamPathTemplate": "/api/products",
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [
{
"Host": "jsonplaceholder.typicode.com",
"Port": 80
}
],
"UpstreamPathTemplate": "/products",
"UpstreamHttpMethod": [ "Post" ],
"QoSOptions": {
"ExceptionsAllowedBeforeBreaking": 3,
"DurationOfBreak": 10,
"TimeoutValue": 5000
}
},
{
"DownstreamPathTemplate": "/api/products/{productId}",
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [
{
"Host": "jsonplaceholder.typicode.com",
"Port": 80
}
],
"UpstreamPathTemplate": "/products/{productId}",
"UpstreamHttpMethod": [ "Put" ],
"QoSOptions": {
"ExceptionsAllowedBeforeBreaking": 3,
"DurationOfBreak": 10,
"TimeoutValue": 5000
},
"FileCacheOptions": { "TtlSeconds": 15 }
},
{
"DownstreamPathTemplate": "/posts",
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [
{
"Host": "jsonplaceholder.typicode.com",
"Port": 80
}
],
"UpstreamPathTemplate": "/posts/",
"UpstreamHttpMethod": [ "Get" ],
"QoSOptions": {
"ExceptionsAllowedBeforeBreaking": 3,
"DurationOfBreak": 10,
"TimeoutValue": 5000
},
"FileCacheOptions": { "TtlSeconds": 15 }
},
{
"DownstreamPathTemplate": "/",
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [
{
"Host": "www.bbc.co.uk",
"Port": 80
}
],
"UpstreamPathTemplate": "/bbc/",
"UpstreamHttpMethod": [ "Get" ]
}
],
"GlobalConfiguration": {
"RequestIdKey": "ot-traceid"
}
}
有关如何使用这些选项的更多信息如下。
多环境
和其他任何asp.net core
项目一样,Ocelot
支持像configuration.dev.json
、configuration.test.json
等的配置文件名。为了实现多环境配置,需要添加如下的代码。
.ConfigureAppConfiguration((hostingContext, config) =>
{
config
.SetBasePath(hostingContext.HostingEnvironment.ContentRootPath)
.AddJsonFile("appsettings.json", true, true)
.AddJsonFile($"appsettings.{hostingContext.HostingEnvironment.EnvironmentName}.json", true, true)
.AddJsonFile("ocelot.json")
.AddJsonFile($"configuration.{hostingContext.HostingEnvironment.EnvironmentName}.json")
.AddEnvironmentVariables();
})
Ocelot
现在将使用特定于环境的配置,如果没有,则返回到ocelot.json
。
您还需要设置相应的ASPNETCORE_ENVIRONMENT
环境变量。更多信息可以查看asp.net core
文档.
合并配置文件
此功能在问题Issue 296
提出要求,并允许用户有多个配置文件,以便管理大型配置。
不直接使用.AddJsonFile("ocelot.json")
这样添加配置,还可以使用AddOcelot()
方法添加
.ConfigureAppConfiguration((hostingContext, config) =>
{
config
.SetBasePath(hostingContext.HostingEnvironment.ContentRootPath)
.AddJsonFile("appsettings.json", true, true)
.AddJsonFile($"appsettings.{hostingContext.HostingEnvironment.EnvironmentName}.json", true, true)
.AddOcelot(hostingContext.HostingEnvironment)
.AddEnvironmentVariables();
})
在这种情况下,Ocelot
将查找与模式(?i)ocelot.([a-zA-Z0-9]*).json
匹配的任何文件,然后将它们合并。 如果你想设置GlobalConfiguration
属性,你必须有一个名为ocelot.global.json
的文件。
Ocelot
合并文件的方式基本上是加载、循环它们,添加所有ReRoutes
,添加所有AggregateReRoutes
,如果文件名为ocelot.global.json
,则添加GlobalConfiguration
以及所有ReRoutes
或AggregateReRoutes
。 然后Ocelot
将合并后的配置保存到一个名为ocelot.json
的文件中,这才是ocelot
运行时配置的真正来源。
目前在这个阶段没有验证,只有当Ocelot
最终合并配置时才会发生验证。 当你排查问题时要注意这一点。如果您有任何问题,建议您始终检查ocelot.json
中的内容。
您还可以给Ocelot
一个特定的路径来查找如下所示的配置文件
.ConfigureAppConfiguration((hostingContext, config) =>
{
config
.SetBasePath(hostingContext.HostingEnvironment.ContentRootPath)
.AddJsonFile("appsettings.json", true, true)
.AddJsonFile($"appsettings.{hostingContext.HostingEnvironment.EnvironmentName}.json", true, true)
.AddOcelot("/foo/bar", hostingContext.HostingEnvironment)
.AddEnvironmentVariables();
})
Ocelot
需要HostingEnvironment
,因此它知道要从算法中排除任何特定的环境。
将配置存储在consul
中
您需要做的第一件事是安装在Ocelot
中提供Consul
支持的NuGet
软件包。
Install-Package Ocelot.Provider.Consul
如果您在注册服务时添加以下内容,Ocelot
将尝试在consul
的KV
数据中存储和检索其配置。
services
.AddOcelot()
.AddConsul()
.AddConfigStoredInConsul();
您还需要将以下内容添加到您的ocelot.json
中。 这使Ocelot
知道如何找到您的Consul
代理并进行交互以及从Consul
加载和存储配置。
"GlobalConfiguration": {
"ServiceDiscoveryProvider": {
"Host": "localhost",
"Port": 9500
}
}
我在研究过raft
算法并发现其超级之难后决定创建此功能。 为什么不利用Consul
已经给你的这个便利呢!我想这意味着如果你想最大限度地使用Ocelot
,你现在就需要将Consul
作为依赖。
此功能在向本地consul
代理发出新请求之前有3秒TTL
缓存。
更改时重新加载JSON
配置
Ocelot
支持更改时重新加载json
配置文件。 例如 当手动更新ocelot.json
文件时,以下内容将重新创建Ocelots
内部配置。
config.AddJsonFile("ocelot.json", optional: false, reloadOnChange: true);
Configuration Key
如果您正在使用Consul
进行配置(或将来使用其他提供程序),则可能需要输入配置密钥,以便可以使用多个配置:)在问题346中,要求使用此功能! 为了指定密钥,您需要在配置json
文件的ServiceDiscoveryProvider
部分中设置ConfigurationKey
属性,例如
"GlobalConfiguration": {
"ServiceDiscoveryProvider": {
"Host": "localhost",
"Port": 9500,
"ConfigurationKey": "Oceolot_A"
}
}
在此示例中,当在Consul
中查找时,Ocelot
将使用Oceolot_A
作为配置的键。
如果未设置ConfigurationKey
,则Ocelot
将使用字符串InternalConfiguration
作为键。
重定向 / 使用CookieContainer
在ReRoute
配置中使用HttpHandlerOptions
来设置HttpHandler
行为:
AllowAutoRedirect
的值指示请求是否应该遵循重定向响应。 如果请求应该自动重定向来自下游资源的响应,请将其设置为true
; 否则为false
。 默认值是false
。UseCookieContainerd
的值指示处理程序是否使用CookieContainer
属性存储服务器cookie
,并在发送请求时使用这些cookie
。默认值是false。值得注意的是,如果您使用CookieContainer
,Ocelot
为每个下游服务缓存HttpClient
。这意味着对该下游的所有请求都将共享相同的Cookie
。问题274的提出是因为用户观察到Cookie
被共享了。我试图想出一个好的解决方案,但我认为是不可能的。如果您不缓存客户端,这意味着每个请求都获得一个新客户端并因此获得一个新的cookie
容器。如果您清除缓存客户端容器中的Cookie
,则会因为正在进行的请求而竞争。这也意味着后续请求不能使用以前响应中的cookie
!总而言之,这不是一个好的局面。我会避免将UseCookieContainer
设置为true
,除非有一个非常好的理由。只需查看您的响应头,并在您的下一个请求把cookie
转发回来!
SSL Errors
如果您想忽略SSL警告/错误,请在ReRoute
配置中设置以下内容。
"DangerousAcceptAnyServerCertificateValidator": true
我不建议这么做,如果可以我建议你创建自己的证书,然后让本地/远程的机器信任它。