Ocelot 中文文档二

本贴最后更新于 1731 天前,其中的信息可能已经时移世改

GraphQL

好吧!你明白我的意思 Ocelot 并不直接支持 GraphQL,但有这么多人问起它,我想表明整合 graphql-dotnet 库是多么容易

请参阅示例项目 OcelotGraphQL。 结合使用 graphql-dotnet 项目和 Ocelot 的 DelegatingHandler 功能,这很容易实现。 不过,我现在不打算更加密切地与 GraphQL 集成。 查看示例的自述文件,应该给了你足够的指导如何去做!

祝你好运,玩得开心:>

服务发现

Ocelot 允许您指定服务发现提供程序,并使用它来查找 Ocelot 正在将请求转发给下游服务的主机和端口。目前,这仅在 GlobalConfiguration 部分中受支持,这意味着所有 ReRoute 将使用相同的服务发现提供程序,以便在 ReRoute 级别指定 ServiceName。

Consul

GlobalConfiguration 中需要以下内容。 提供者是必需的,如果你没有指定主机和端口,默认使用 Consul。

"ServiceDiscoveryProvider": {
    "Host": "localhost",
    "Port": 9500
}

将来我们可以添加一个功能,允许 ReRoute 配置服务发现提供程序。

为了告诉 Ocelot 一个 ReRoute 需要使用服务发现提供程序来发现下游主机和端口,您必须在下游请求配置中添加 ServiceName,UseServiceDiscovery 和 LoadBalancer。 目前 Ocelot 有 RoundRobin(轮询)和 LeastConnection(最少连接)两个负载均衡的算法。 如果没有指定负载均衡器,Ocelot 将不会均衡请求。

{
    "DownstreamPathTemplate": "/api/posts/{postId}",
    "DownstreamScheme": "https",
    "UpstreamPathTemplate": "/posts/{postId}",
    "UpstreamHttpMethod": [ "Put" ],
    "ServiceName": "product",
    "LoadBalancer": "LeastConnection",
    "UseServiceDiscovery": true
}

如此设置之后,Ocelot 将从服务发现提供程序查找下游主机和端口,并通过可用服务平衡请求。

ACL Token

如果您使用 Consul 的 ACL,Ocelot 也支持添加 X-Consul-Token 头。 为了实现 ACL 访问,您必须添加下面的附加属性 Token。

"ServiceDiscoveryProvider": {
    "Host": "localhost",
    "Port": 9500,
    "Token": "footoken"
}

Ocelot 会将这个令牌添加到用来发出请求的 consul 客户端,然后用于后续的每个请求。

Eureka

这个功能是作为问题 262 的一部分被提出。为 Netflix 的 Eureka 服务发现提供程序添加支持。 主要原因是它是 Steeltoe 的一个关键部分,Steeltoe 又与 Pivotal 有关! 反正背景很牛逼。

为了使 Eureka 工作,需要在 ocelot.json 中添加如下配置..

"ServiceDiscoveryProvider": {
    "Type": "Eureka"
}

遵循这里的指导,您可能还需要添加一些内容到 appsettings.json。 例如,下面的 json 告诉 steeltoe/关键服务在哪里寻找服务发现服务器,以及服务是否应该向其注册。

"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 包提供,所以非常感谢他们的辛勤工作。

微服务 ServiceFabric

如果您在 Service Fabric 中部署了服务,则通常会使用命名服务来访问它们。

以下示例展示如何设置一个 ReRoute 以便在在 Service Fabric 中工作。 最重要的是 ServiceName,它由 Service Fabric 应用程序名称和特定服务名称组成的。 我们还需要将 UseServiceDiscovery 设置为 true,并在 GlobalConfiguration 中设置 ServiceDiscoveryProvider。 这里的例子显示了一个典型的配置。 它假定 Service Fabric 在本地主机上运行,并且命名服务位于 19081 端口上。

下面的例子来例子本文件夹,所以请检查它配置是否与你的实际情况相符!

    "ReRoutes": [
        {
        "DownstreamPathTemplate": "/api/values",
        "UpstreamPathTemplate": "/EquipmentInterfaces",
        "UpstreamHttpMethod": [
            "Get"
        ],
        "DownstreamScheme": "http",
        "ServiceName": "OcelotServiceApplication/OcelotApplicationService",
        "UseServiceDiscovery" :  true
        }
    ],
    "GlobalConfiguration": {
        "RequestIdKey": "OcRequestId",
        "ServiceDiscoveryProvider": {
            "Host": "localhost",
            "Port": 19081,
            "Type": "ServiceFabric"
        }
    }
}

如果您使用无状态/ guest exe 服务,ocelot 将能够通过命名服务进行代理,而无需其他任何操作。 但是,如果您使用的是有状态/actor 服务,则客户端请求必须发送 PartitionKind 和 PartitionKey 查询字符串。

GET http://ocelot.com/EquipmentInterfaces?PartitionKind=xxx&PartitionKey=xxx

Ocelot 无法为您解决这个问题。

认证

为了验证 ReRoutes 并随后使用 Ocelot 的任何基于声明的功能,如授权或使用令牌中的值修改请求。 用户必须像往常一样在他们的 Startup.cs 中注册认证服务,但他们给每个注册提供了一个方案(认证提供商密钥),例如

{
    var authenticationProviderKey = "TestKey";

    services.AddAuthentication()
        .AddJwtBearer(authenticationProviderKey, x =>
        {
        });
}

在此示例中,TestKey 是此提供程序已注册的方案。 然后,我们将其映射到配置中的 ReRoute,例如

"ReRoutes": [{
        "DownstreamHostAndPorts": [
            {
                "Host": "localhost",
                "Port": 51876,
            }
        ],
        "DownstreamPathTemplate": "/",
        "UpstreamPathTemplate": "/",
        "UpstreamHttpMethod": ["Post"],
        "ReRouteIsCaseSensitive": false,
        "DownstreamScheme": "http",
        "AuthenticationOptions": {
            "AuthenticationProviderKey": "TestKey",
            "AllowedScopes": []
        }
    }]

当 Ocelot 运行时,它会查看此 ReRoutes 的 AuthenticationOptions.AuthenticationProviderKey 并检查是否存在给定密钥注册的身份验证提供程序。 如果没有,那么 Ocelot 不会启动,如果有的话 ReRoute 将在执行时使用该提供者。

如果 ReRoute 配置了认证,Ocelot 在执行认证中间件时将调用与其相关的任何验证方案。 如果请求认证失败,Ocelot 返回 http 状态码 401。

JWT 令牌

如果您想使用 JWT 令牌进行身份验证,例如 Auth0 等提供商,您可以使用正常的方式注册你的身份验证中间件。

public void ConfigureServices(IServiceCollection services)
{
    var authenticationProviderKey = "TestKey";

    services.AddAuthentication()
        .AddJwtBearer(authenticationProviderKey, x =>
        {
            x.Authority = "test";
            x.Audience = "test";
        });

    services.AddOcelot();
}

然后将身份验证提供程序密钥映射到配置中的 ReRoute,例如

"ReRoutes": [{
        "DownstreamHostAndPorts": [
            {
                "Host": "localhost",
                "Port": 51876,
            }
        ],
        "DownstreamPathTemplate": "/",
        "UpstreamPathTemplate": "/",
        "UpstreamHttpMethod": ["Post"],
        "ReRouteIsCaseSensitive": false,
        "DownstreamScheme": "http",
        "AuthenticationOptions": {
            "AuthenticationProviderKey": "TestKey",
            "AllowedScopes": []
        }
    }]

Identity Server 承载令牌

为了使用 IdentityServer 承载令牌,请按照惯例在 ConfigureServices 中使用方案(密钥)注册您的 IdentityServer 服务。 如果您不明白如何操作,请访问 IdentityServer 文档。

public void ConfigureServices(IServiceCollection services)
{
    var authenticationProviderKey = "TestKey";
    var options = o =>
        {
            o.Authority = "https://whereyouridentityserverlives.com";
            o.ApiName = "api";
            o.SupportedTokens = SupportedTokens.Both;
            o.ApiSecret = "secret";
        };

    services.AddAuthentication()
        .AddIdentityServerAuthentication(authenticationProviderKey, options);

    services.AddOcelot();
}

然后将身份验证提供程序密钥映射到配置中的 ReRoute,例如

"ReRoutes": [{
        "DownstreamHostAndPorts": [
            {
                "Host": "localhost",
                "Port": 51876,
            }
        ],
        "DownstreamPathTemplate": "/",
        "UpstreamPathTemplate": "/",
        "UpstreamHttpMethod": ["Post"],
        "ReRouteIsCaseSensitive": false,
        "DownstreamScheme": "http",
        "AuthenticationOptions": {
            "AuthenticationProviderKey": "TestKey",
            "AllowedScopes": []
        }
    }]

允许的范围

如果将范围添加到 AllowedScopes,Ocelot 将获得类型范围的所有用户声明(从令牌中),并确保用户具有列表中的所有范围。

这是一种基于范围限制对 ReRoute 访问的方式。

授权

Ocelot 支持基于声明的授权。 这意味着如果您有要授权的路由,您可以将以下内容添加到您的 ReRoute 配置中。

"RouteClaimsRequirement": {
    "UserType": "registered"
}

在此示例中,授权中间件被调用时,Ocelot 将检查用户是否拥有声明类型 UserType 以及该声明的值是否是 registered。 如果不是,那么用户将不会被授权,并且响应将被禁止。

Websockets

Ocelot 额外支持代理 websockets。这个功能在问题 212 中被提出。

为了是 Ocelot 代理 websocket,你需要做如下事情。

在你的 Configure 方法中,你要告知应用程序使用 WebSockets。

 Configure(app =>
{
    app.UseWebSockets();
    app.UseOcelot().Wait();
})

然后在你的 ocelot.json 中添加如下代码,用于配置 websockets 代理一个 ReRoute。

{
     "DownstreamPathTemplate": "/ws",
     "UpstreamPathTemplate": "/",
     "DownstreamScheme": "ws",
     "DownstreamHostAndPorts": [
         {
             "Host": "localhost",
             "Port": 5001
         }
     ],
 }

使用这个配置,Ocelot 将匹配所有进入的 Websocket 流量并将其代理到 localhost:5001/ws。 更清晰的解释一下就是,Ocelot 将接收来自上游客户端的消息,并将它们代理到下游服务,从下游服务接收消息并将这些消息代理到上游客户端。

已支持的

  1. 负载均衡
  2. 路由
  3. 服务发现

这意味着您可以运行 websockets 的下游服务,并在您的 ReRoute 配置中使用多个 DownstreamHostAndPorts,或将您的 ReRoute 挂接到服务发现提供程序上,然后负载均衡上游请求......我认为这很酷:)

不支持的

不幸的是,很多 Ocelot 的功能都是非 websocket 所特有的,比如 header 和 http 客户端填充。 我列出了以下不适用的功能。

  1. 跟踪
  2. 请求 Id
  3. 请求聚合
  4. 流量限制
  5. 服务质量
  6. 中间件注入
  7. 转换 Header
  8. 委托处理程序
  9. 转换声明
  10. 缓存
  11. 认证 - 如果有人请求它,我们可能可以使用基本身份验证做些事情
  12. 授权

我不是 100%确定这个功能在进入高速运转时会发生什么,所以请确保您彻底测试过!

管理

Ocelot 支持在运行时通过一个认证的 Http API 修改配置。有两种方式对其验证, 使用 Ocelot 的内置 IdentityServer(仅用于向管理 API 验证请求)或将管理 API 验证挂接到您自己的 IdentityServer 中。

提供你自己的 IdentityServer

挂接到你自己的 IdentityServer,你只需要添加一下代码到你的 ConfigureServices 方法中。

public virtual void ConfigureServices(IServiceCollection services)
{
    Action<IdentityServerAuthenticationOptions> options = o => {
            // o.Authority = ;
            // o.ApiName = ;
            // etc....
        };

    services
        .AddOcelot()
        .AddAdministration("/administration", options);
}

您现在需要从你的 IdentityServer 获取令牌,并在后续请求 Ocelot 的管理 API 时使用。

这个功能是对问题 228 的实现。这个功能很有用,因为 IdentityServer 认证中间件需要 IdentityServer 的 URL。 如果您使用内置 IdentityServer,则可能无法获得 Ocelot URL。

内置 IdentityServer

管理 API 使用您从 Ocelot 请求的持票人令牌进行身份验证。这是由我已经使用了几年的非常了不起的 Identity Server 项目提供的。 您可以去看一下。

为了启用管理部分,您需要做一些操作。 首先将此添加到您的初始化文件 Startup.cs 中。

管理路径可以是任何值,显然不能使用将要通过 Ocelot 路由的 url,因为这是行不通的。管理功能使用 asp.net core 的 MapWhen 功能,并且所有到{root} /administration 的请求将被发送到那里,而不是 Ocelot 中间件。

secret 是 Ocelot 内置 IdentityServer 用于验证对管理 API 请求的客户端密钥。你可以随意填写!

public virtual void ConfigureServices(IServiceCollection services)
{
    services
        .AddOcelot()
        .AddAdministration("/administration", "secret");
}

现在,如果您使用上述配置选项并想要访问 API,可以使用解决方案中名为 ocelot.postman_collection.json 的 postman 脚本来更改 Ocelot 配置。 显然,如果 Ocelot 运行在不同与 http://localhost:5000 的 URL 上,则需要改一下。

这些脚本向您展示了如何从 ocelot 请求 bearer 令牌,然后使用它来获取现有配置和修改配置。

如果您在群集中运行多个 Ocelot,则需要使用证书对用于访问管理 API 的 bearer 令牌签名。

为了做到这一点,您需要为集群中的每个 Ocelot 再添加两个的环境变量。

OCELOT_CERTIFICATE
用于签名令牌的证书路径。 证书必须是 X509 类型,显然 Ocelot 要能够访问它。

OCELOT_CERTIFICATE_PASSWORD
证书的密码。

通常 Ocelot 只使用临时签名凭证,但如果您设置了这些环境变量,那么它将使用设置的证书。 如果集群中的所有其他 Ocelot 都具有相同的证书,那很棒,这样就对了!

管理 API

POST {adminPath}/connect/token

这会使用我们上面讨论的客户端证书得到一个用于管理区域的令牌。 在这种情况下,这将调用 Ocelot 中托管的 IdentityServer。

请求体是 from-data,允许一下数据:

client_id 设置为 admin

client_secret 设置为您在设置管理服务时使用的内容

scope 设置为 admin

grant_type 设置为 client_credentials

GET {adminPath}/configuration

获得当前的 Ocelot 配置。 这与我们先前设置 Ocelot 的 JSON 完全相同。

POST {adminPath}/configuration

这会覆盖现有的配置(可能应该是 put 更合适!)。 我建议用 GET 获取您的配置,进行更改后使用此 api 发回...。

这个请求体的 JSON,格式和我们使用文件系统设置 Ocelot 的 FileConfiguration.cs 格式相同

DELETE {adminPath}/outputcache/{region}

这将清空特定区域的缓存。如果您使用空白 region,它将清除缓存的所有实例!赋予您运行 Ocelots 集群,并将其全部缓存在内存中,并同时清除所有缓存(仅使用分布式缓存)的能力。

region 是您在 Ocelot 配置的 FileCacheOptions 部分中针对 region 字段设置的内容。

流量控制

感谢 @catcherwong 的文章激励我最终写出了这个文档

Ocelot 支持上游的请求限制,以便您的下游服务不会过载。 此功能是由 GitHub 上的 @geffzhang 添加! 非常感谢。

好了,为了让 ReRoute 获得流量限制,你需要添加下面的 json 到 ReRoute 中。

"RateLimitOptions": {
    "ClientWhitelist": [],
    "EnableRateLimiting": true,
    "Period": "1s",
    "PeriodTimespan": 1,
    "Limit": 1
}

ClientWhitelist - 是一个包含客户端白名单列表的数组。这意味着在白名单里的客户端不受流量限制的影响。
EnableRateLimiting - 该值指定流量限制是否开启。
Period - 该值指定时间段,例如 1s,5m,1h,1d 等。
PeriodTimespan - 该值指定我们可以在一定的秒数后重试。
Limit - 该值指定一个客户端可以在定义的时间段(Period)内允许的最大请求数。

您还可以在 ocelot.json 的 GlobalConfiguration 部分中设置以下内容

"RateLimitOptions": {
  "DisableRateLimitHeaders": false,
  "QuotaExceededMessage": "Customize Tips!",
  "HttpStatusCode": 999,
  "ClientIdHeader" : "Test"
}

DisableRateLimitHeaders - 该值指定是否禁用 X-Rate-Limit 和 Rety-After 头。
QuotaExceededMessage - 该值指定超出限制时返回的消息。
HttpStatusCode - 该值指定超出限制时返回的 HTTP 状态代码。
ClientIdHeader - 允许您指定应该用于标识客户端的头。 默认是“ClientId”

缓存

目前 Ocelot 使用 CacheManager 项目提供了一些非常基本的缓存。这是一个了不起的项目,它解决了很多缓存问题。 我会推荐这个软件包来做 Ocelot 缓存。 如果你看看这里的例子,你可以看到如何设置缓存管理器,然后传入 Ocelot 的 AddOcelotOutputCaching 配置方法。 您可以使用 CacheManager 软件包支持的任何设置,只需传入即可。

无论如何,Ocelot 目前支持对下游服务的 URL 进行缓存,并可以设置一个以秒为单位的 TTL 使缓存过期。 您也可以通过调用 Ocelot 的管理 API 来清除某个 Region 的缓存。

为了在路由中使用缓存,需要在 ReRoute 中加上如下设置。

"FileCacheOptions": { "TtlSeconds": 15, "Region": "somename" }

示例中 ttl 设置为 15 表示缓存在 15 秒后过期。

Qos 服务质量

目前 Ocelot 支持一种 QoS 功能。 如果您希望在请求向下游服务时使用断路,则可以在 ReRoute 中进行设置。 这个功能使用了一个名为 Polly 的.NET 库,这个库很棒,在这里可以找到它。

添加如下配置块到一个 ReRoute 配置中。

"QoSOptions": {
    "ExceptionsAllowedBeforeBreaking":3,
    "DurationOfBreak":5,
    "TimeoutValue":5000
}

为了实现这个规则,你必须设置一个大于 0 的数字给 ExceptionsAllowedBeforeBreaking。DurationOfBreak 是断路器跳闸后保持断开的时间。TimeoutValue 表示如果请求超过 5 秒钟,它将自动超时。

你可以单独设置 TimeoutValue 选项,而不设置 ExceptionsAllowedBeforeBreaking 和 DurationOfBreak 。

"QoSOptions": {
    "TimeoutValue":5000
}

单独设置另外两个选项其中之一是没有意义的,因为他们两个相互影响。

如果您不添加 QoS 部分,QoS 将不会被使用,但 Ocelot 默认将所有下游请求的超时时间设置为 90 秒。 如果有人需要这个 90 秒是可配置,请提出问题。

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...