Ocelot
允许您指定服务发现提供程序,并使用它来查找Ocelot
正在将请求转发给下游服务的主机和端口。目前,这仅在GlobalConfiguration
部分中受支持,这意味着所有Route
将使用相同的服务发现提供程序,以便在Route
级别指定ServiceName
。
Consul
您需要做的第一件事是安装在Ocelot
中提供Consul
支持的NuGet
软件包。
Install-Package Ocelot.Provider.Consul
然后将以下内容添加到您的ConfigureServices
方法中。
s.AddOcelot()
.AddConsul();
GlobalConfiguration
中需要以下内容。 提供者是必需的,如果你没有指定主机和端口,默认使用Consul。
"ServiceDiscoveryProvider": {
"Host": "localhost",
"Port": 8500,
"Type": "Consul"
}
将来我们可以添加一个功能,允许Route
配置服务发现提供程序。
为了告诉Ocelot一个Route
需要使用服务发现提供程序来发现下游主机和端口,您必须在下游请求配置中添加ServiceName
和LoadBalancer
。 目前Ocelot有RoundRobin
(轮询)和LeastConnection
(最少连接)两个负载均衡的算法。 如果没有指定负载均衡器,Ocelot将不会均衡请求。
{
"DownstreamPathTemplate": "/api/posts/{postId}",
"DownstreamScheme": "https",
"UpstreamPathTemplate": "/posts/{postId}",
"UpstreamHttpMethod": [ "Put" ],
"ServiceName": "product",
"LoadBalancerOptions": {
"Type": "LeastConnection"
},
}
设置此选项后,Ocelot将从服务发现提供程序中查找下游主机和端口,并在所有可用服务中进行负载平衡请求。
很多人要求我实现一项功能,即Ocelot轮询Consul以获取最新的服务信息,而不是根据每个请求。 如果要轮询Consul以获得最新服务,而不是按请求(默认行为)进行轮询,则需要设置以下配置。
"ServiceDiscoveryProvider": {
"Host": "localhost",
"Port": 8500,
"Type": "PollConsul",
"PollingInterval": 100
}
轮询间隔以毫秒为单位,告诉Ocelot多久调用一次Consul
来更改服务配置。
请注意,这里需要权衡。 如果您对Consul进行轮询,则Ocelot可能会根据轮询间隔不知道服务是否关闭,并且与每个请求获得最新服务相比,您可能会遇到更多错误。 这实际上取决于您的服务的不稳定程度。 我怀疑这对大多数人来说是否重要,而轮询可能会比按请求(作为便车代理)调用Consul的性能有所改善。 如果您呼叫远程Consul代理,则轮询将改善性能。
需要将您的服务添加到Consul中,如下所示(C#样式,但希望这是有道理的)…要注意的唯一重要的事情是不要在Address
字段中添加http
或https
。 之前已经联系过我关于不接受地址中的方案和地址中的方案的联系。 看完这篇文章后,我认为该方案不应该存在。
还可以
"Service": {
"ID": "some-id",
"Service": "some-service-name",
"Address": "localhost",
"Port": 8080
}
ACL Token
如果您使用Consul的ACL
,Ocelot也支持添加X-Consul-Token
头。 为了实现ACL
访问,您必须添加下面的附加属性Token
。
"ServiceDiscoveryProvider": {
"Host": "localhost",
"Port": 8500,
"Token": "footoken",
"Type": "Consul"
}
Ocelot会将这个令牌添加到用来发出请求的Consul
客户端,然后用于后续的每个请求。
Eureka
这个功能是作为问题 262的一部分被提出。为Netflix的Eureka
服务发现提供程序添加支持。 主要原因是它是Steeltoe
的一个关键部分,Steeltoe又与Pivotal有关! 反正背景很牛逼。
您需要做的第一件事是在Ocelot中安装提供Eureka支持的NuGet软件包。
Install-Package Ocelot.Provider.Eureka
然后将以下内容添加到您的ConfigureServices
方法中。
s.AddOcelot()
.AddEureka();
为了使Eureka
工作,需要在 ocelot.json
中添加如下配置.
"ServiceDiscoveryProvider": {
"Type": "Eureka"
}
遵循这里的指导,您可能还需要添加一些内容到appsettings.json
。 例如,下面的json
告诉steeltoe/pivotal
服务在哪里寻找服务发现服务器,以及服务是否应该向其注册。
"eureka": {
"client": {
"serviceUrl": "http://localhost:8761/eureka/",
"shouldRegisterWithEureka": false,
"shouldFetchRegistry": true
}
}
我被告知,如果shouldRegisterWithEureka
是false
,那么shouldFetchRegistry
将会默认为true
,所以你不需要显式地将它留在这里。
现在Ocelot将在启动时注册所有必要的服务,并且如果配置有上述json,则会将其注册到Eureka
。其中一项服务每30秒(默认)轮询一次Eureka
获取最新的服务状态并将其保留在内存中。当Ocelot要求提供给定的服务时,它会从内存中检索出来,因此性能不是一个大问题。注意,此代码由Pivotal.Discovery.Client
的NuGet
包提供,所以非常感谢他们的辛勤工作。
Dynamic Routing
在发行版340中请求了此功能。其思想是在使用服务发现提供程序时启用动态路由(有关更多信息,请参阅文档的该部分)。在这种模式下,Ocelot将使用上游路径的第一段通过服务发现提供程序查找下游服务。
这样的一个例子是使用诸如https://api.mywebsite.com/product/products
之类的URL调用Ocelot。 Ocelot将采用路径的第一部分即产品,并将其用作在Consul中查找服务的键。如果Consul返回服务,则Ocelot将在Consul返回的任何主机和端口以及本例中产品的其余路径段上请求该服务,从而进行下游调用http://hostfromconsul:portfromconsul/products
。 Ocelot将像往常一样将任何查询字符串添加到下游URL。
为了启用动态路由,您的配置中需要有0条路由。目前,您无法混合使用动态路由和配置路由。除此之外,您还需要指定上述服务发现提供者详细信息,并将下游http / https方案指定为DownstreamScheme
。
除此之外,您还可以设置RateLimitOptions,QoSOptions,LoadBalancerOptions
和HttpHandlerOptions,DownstreamScheme
(您可能希望在https
上调用Ocelot,但通过http
与私有服务对话)将应用于所有动态路由。
配置可能看起来像
{
"ReRoutes": [],
"Aggregates": [],
"GlobalConfiguration": {
"RequestIdKey": null,
"ServiceDiscoveryProvider": {
"Host": "localhost",
"Port": 8500,
"Type": "Consul",
"Token": null,
"ConfigurationKey": null
},
"RateLimitOptions": {
"ClientIdHeader": "ClientId",
"QuotaExceededMessage": null,
"RateLimitCounterPrefix": "ocelot",
"DisableRateLimitHeaders": false,
"HttpStatusCode": 429
},
"QoSOptions": {
"ExceptionsAllowedBeforeBreaking": 0,
"DurationOfBreak": 0,
"TimeoutValue": 0
},
"BaseUrl": null,
"LoadBalancerOptions": {
"Type": "LeastConnection",
"Key": null,
"Expiry": 0
},
"DownstreamScheme": "http",
"HttpHandlerOptions": {
"AllowAutoRedirect": false,
"UseCookieContainer": false,
"UseTracing": false
}
}
}
Ocelot还允许您设置DynamicRoutes
,从而可以为每个下游服务设置速率限制规则。 例如,如果您有产品和搜索服务,并且想要对两者进行最高限价,这将非常有用。 一个例子如下。
{
"DynamicReRoutes": [
{
"ServiceName": "product",
"RateLimitRule": {
"ClientWhitelist": [],
"EnableRateLimiting": true,
"Period": "1s",
"PeriodTimespan": 1000.0,
"Limit": 3
}
}
],
"GlobalConfiguration": {
"RequestIdKey": null,
"ServiceDiscoveryProvider": {
"Host": "localhost",
"Port": 8523,
"Type": "Consul"
},
"RateLimitOptions": {
"ClientIdHeader": "ClientId",
"QuotaExceededMessage": "",
"RateLimitCounterPrefix": "",
"DisableRateLimitHeaders": false,
"HttpStatusCode": 428
}
"DownstreamScheme": "http",
}
}
此配置意味着,如果您有一个请求进入/product/*
上的Ocelot,则动态路由将启动,并且ocelot将使用DynamicRoutes
部分中针对产品服务设置的速率限制。
请浏览所有文档以了解这些选项。
Service Fabric
如果您在Service Fabric中部署了服务,则通常将使用命名服务来访问它们。
以下示例显示了如何设置将在Service Fabric中工作的路由。 最重要的是ServiceName
,它由Service Fabric
应用程序名称和特定的服务名称组成。 我们还需要在GlobalConfiguration
中设置ServiceDiscoveryProvider
。 此处的示例显示了典型配置。 假定服务结构在本地主机上运行,并且命名服务在端口19081上。
下面的示例取自samples文件夹,因此,如果这没有意义,请进行检查!
{
"ReRoutes": [
{
"DownstreamPathTemplate": "/api/values",
"UpstreamPathTemplate": "/EquipmentInterfaces",
"UpstreamHttpMethod": [
"Get"
],
"DownstreamScheme": "http",
"ServiceName": "OcelotServiceApplication/OcelotApplicationService",
}
],
"GlobalConfiguration": {
"RequestIdKey": "OcRequestId",
"ServiceDiscoveryProvider": {
"Host": "localhost",
"Port": 19081,
"Type": "ServiceFabric"
}
}
}
如果您使用无状态/guest
服务,则ocelot将能够通过命名服务进行代理,而无需其他任何操作。 但是,如果您使用statefull /actor
服务,则必须随客户端请求一起发送PartitionKind
和PartitionKey
查询字符串值,例如
GET http://ocelot.com/EquipmentInterfaces?PartitionKind=xxx&PartitionKey=xxx
Ocelot无法为您解决这些问题。