.NET Core API网关Ocelot(十六)【负载均衡】

Ocelot能通过可用的下游服务对每个Route进行负载平衡。 这意味着您可以扩展您的下游服务,并且Ocelot可以有效地使用它们。

可用的负载均衡器的类型是:

  • LeastConnection -最少连接,跟踪哪些服务正在处理请求,并把新请求发送到现有请求最少的服务上。该算法状态不在整个Ocelot集群中分布。
  • RoundRobin - 轮询可用的服务并发送请求。 该算法状态不在整个Ocelot集群中分布。
  • NoLoadBalancer - 不负载均衡,从配置或服务发现提供程序中取第一个可用的下游服务。
  • CookieStickySessions - 使用cookie关联所有相关的请求到制定的服务。下面有更多信息。

你必须在你的配置中选择使用哪种负载均衡方式。

配置

下面展示了如何使用ocelot.json给一个Route设置多个下游服务,并选择LeadConnection负载均衡器。这是设置负载均衡最简单的方法。

{
    "DownstreamPathTemplate": "/api/posts/{postId}",
    "DownstreamScheme": "https",
    "DownstreamHostAndPorts": [
            {
                "Host": "10.0.1.10",
                "Port": 5000,
            },
            {
                "Host": "10.0.1.11",
                "Port": 5000,
            }
        ],
    "UpstreamPathTemplate": "/posts/{postId}",
    "LoadBalancerOptions": {
        "Type": "LeastConnection"
    },
    "UpstreamHttpMethod": [ "Put", "Delete" ]
}

服务发现

下面展示了如何使用服务发现设置一个Route,并选择LeadConnection负载均衡器。

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

设置此操作时,Ocelot将从服务发现提供程序查找下游主机和端口,并通过所有可用服务来负载均衡请求。 如果您向服务发现提供程序(consul)添加和删除服务,那么Ocelot将遵循这一点,停止调用已被删除的服务并开始调用已添加的服务。

CookieStickySessions

我已经实现了一个非常基本的粘性会话类型的负载平衡器。 它意味着支持的场景是你有一堆不共享会话状态的下游服务器,如果你为其中一台服务器获得多个请求,那么它应该每次都去同一个盒子,否则给用户的会话状态可能不正确。 这个特性在问题#322中有被提出,尽管用户想要的比只是粘性会话更加复杂 : ),无论如何,我认为这是个不错的功能!

为了设置CookieStickySessions负载均衡器,你需要做如下事情。

{
    "DownstreamPathTemplate": "/api/posts/{postId}",
    "DownstreamScheme": "https",
    "DownstreamHostAndPorts": [
            {
                "Host": "10.0.1.10",
                "Port": 5000,
            },
            {
                "Host": "10.0.1.11",
                "Port": 5000,
            }
        ],
    "UpstreamPathTemplate": "/posts/{postId}",
    "LoadBalancerOptions": {
        "Type": "CookieStickySessions",
        "Key": "ASP.NET_SessionId",
        "Expiry": 1800000
    },
    "UpstreamHttpMethod": [ "Put", "Delete" ]
}

LoadBalancerOptionsType需要是CookieStickySessionsKey是您希望用于粘性会话的cookie的名称,Expiry是您希望会话被粘合的时间,以毫秒为单位。 请记住,每次请求都会刷新,这意味着会模仿会话的工作方式(滑动过期–译者注)。

如果您有多个具有相同LoadBalancerOptionsRoutes,那么所有这些Routes将为随后的请求使用相同的负载均衡器。 这意味着会话将会跨Route进行粘合。

请注意,如果您提供多个DownstreamHostAndPort或者您正在使用Consul等服务发现提供程序,并且返回多个服务,则CookieStickySessions将使用循环选择下一个服务器。 目前是硬编码,但可以改变。

自定义负载均衡器

DavidLievrouw _实现了一种在 PR 1155 _中为Ocelot提供自定义负载均衡器的方法。

为了创建和使用自定义负载均衡器,您可以执行以下操作。 在下面,我们设置一个基本的负载均衡配置,而不是TypeCustomLoadBalancer,这是我们将设置为进行负载均衡的类的名称。

{
    "DownstreamPathTemplate": "/api/posts/{postId}",
    "DownstreamScheme": "https",
    "DownstreamHostAndPorts": [
            {
                "Host": "10.0.1.10",
                "Port": 5000,
            },
            {
                "Host": "10.0.1.11",
                "Port": 5000,
            }
        ],
    "UpstreamPathTemplate": "/posts/{postId}",
    "LoadBalancerOptions": {
        "Type": "CustomLoadBalancer"
    },
    "UpstreamHttpMethod": [ "Put", "Delete" ]
}

然后,您需要创建一个实现ILoadBalancer接口的类。 下面是一个简单的循环示例。

private class CustomLoadBalancer : ILoadBalancer
{
    private readonly Func<Task<List<Service>>> _services;
    private readonly object _lock = new object();

    private int _last;

    public CustomLoadBalancer(Func<Task<List<Service>>> services)
    {
        _services = services;
    }

    public async Task<Response<ServiceHostAndPort>> Lease(DownstreamContext downstreamContext, HttpContext httpContext)
    {
        var services = await _services();
        lock (_lock)
        {
            if (_last >= services.Count)
            {
                _last = 0;
            }

            var next = services[_last];
            _last++;
            return new OkResponse<ServiceHostAndPort>(next.HostAndPort);
        }
    }

    public void Release(ServiceHostAndPort hostAndPort)
    {
    }
}

最后,您需要在Ocelot中注册此类。 我使用下面最复杂的示例来展示可以传递给创建负载均衡器的工厂的所有数据/类型。

Func<IServiceProvider, DownstreamRoute, IServiceDiscoveryProvider, CustomLoadBalancer> loadBalancerFactoryFunc = (serviceProvider, Route, serviceDiscoveryProvider) => new CustomLoadBalancer(serviceDiscoveryProvider.Get);

s.AddOcelot()
    .AddCustomLoadBalancer(loadBalancerFactoryFunc);

但是,有一个更简单的示例将起作用。

s.AddOcelot()
    .AddCustomLoadBalancer<CustomLoadBalancer>();

添加自定义负载均衡器的扩展方法有很多,接口如下

IOcelotBuilder AddCustomLoadBalancer<T>()
    where T : ILoadBalancer, new();

 IOcelotBuilder AddCustomLoadBalancer<T>(Func<T> loadBalancerFactoryFunc)
    where T : ILoadBalancer;

 IOcelotBuilder AddCustomLoadBalancer<T>(Func<IServiceProvider, T> loadBalancerFactoryFunc)
    where T : ILoadBalancer;

 IOcelotBuilder AddCustomLoadBalancer<T>(
    Func<DownstreamRoute, IServiceDiscoveryProvider, T> loadBalancerFactoryFunc)
    where T : ILoadBalancer;

 IOcelotBuilder AddCustomLoadBalancer<T>(
    Func<IServiceProvider, DownstreamRoute, IServiceDiscoveryProvider, T> loadBalancerFactoryFunc)
    where T : ILoadBalancer;

当启用自定义负载均衡器时,Ocelot在决定是否应该进行负载均衡时会通过其类名查找您的负载均衡器。 如果找到匹配项,它将使用您的负载平衡器进行负载平衡。 如果Ocelot无法将配置中的负载均衡器类型与已注册的负载均衡器类的名称匹配,则您将收到HTTP 500内部服务器错误。 如果您的负载平衡器工厂在Ocelot调用它时引发异常,您将收到HTTP 500内部服务器错误。

请记住,如果您在配置中未指定任何负载均衡器,Ocelot将不会尝试进行负载均衡。

你可能感兴趣的:(NET,Core跨平台)