mirror of
https://github.com/nsnail/Ocelot.git
synced 2025-06-19 22:08:17 +08:00
Merge branch 'CustomLoadBalancers' of https://github.com/DavidLievrouw/Ocelot into DavidLievrouw-CustomLoadBalancers
This commit is contained in:
@ -3,6 +3,9 @@ using Microsoft.Extensions.DependencyInjection;
|
||||
using Ocelot.Middleware.Multiplexer;
|
||||
using System;
|
||||
using System.Net.Http;
|
||||
using Ocelot.Configuration;
|
||||
using Ocelot.LoadBalancer.LoadBalancers;
|
||||
using Ocelot.ServiceDiscovery.Providers;
|
||||
|
||||
namespace Ocelot.DependencyInjection
|
||||
{
|
||||
@ -25,6 +28,23 @@ namespace Ocelot.DependencyInjection
|
||||
IOcelotBuilder AddTransientDefinedAggregator<T>()
|
||||
where T : class, IDefinedAggregator;
|
||||
|
||||
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<DownstreamReRoute, IServiceDiscoveryProvider, T> loadBalancerFactoryFunc)
|
||||
where T : ILoadBalancer;
|
||||
|
||||
IOcelotBuilder AddCustomLoadBalancer<T>(
|
||||
Func<IServiceProvider, DownstreamReRoute, IServiceDiscoveryProvider, T> loadBalancerFactoryFunc)
|
||||
where T : ILoadBalancer;
|
||||
|
||||
IOcelotBuilder AddConfigPlaceholders();
|
||||
}
|
||||
}
|
||||
|
@ -1,3 +1,5 @@
|
||||
using Ocelot.ServiceDiscovery.Providers;
|
||||
|
||||
using Ocelot.Configuration.ChangeTracking;
|
||||
|
||||
namespace Ocelot.DependencyInjection
|
||||
@ -87,6 +89,10 @@ namespace Ocelot.DependencyInjection
|
||||
Services.TryAddSingleton<IFileConfigurationRepository, DiskFileConfigurationRepository>();
|
||||
Services.TryAddSingleton<IFileConfigurationSetter, FileAndInternalConfigurationSetter>();
|
||||
Services.TryAddSingleton<IServiceDiscoveryProviderFactory, ServiceDiscoveryProviderFactory>();
|
||||
Services.AddSingleton<ILoadBalancerCreator, NoLoadBalancerCreator>();
|
||||
Services.AddSingleton<ILoadBalancerCreator, RoundRobinCreator>();
|
||||
Services.AddSingleton<ILoadBalancerCreator, CookieStickySessionsCreator>();
|
||||
Services.AddSingleton<ILoadBalancerCreator, LeastConnectionCreator>();
|
||||
Services.TryAddSingleton<ILoadBalancerFactory, LoadBalancerFactory>();
|
||||
Services.TryAddSingleton<ILoadBalancerHouse, LoadBalancerHouse>();
|
||||
Services.TryAddSingleton<IOcelotLoggerFactory, AspDotNetLoggerFactory>();
|
||||
@ -169,6 +175,47 @@ namespace Ocelot.DependencyInjection
|
||||
return this;
|
||||
}
|
||||
|
||||
public IOcelotBuilder AddCustomLoadBalancer<T>()
|
||||
where T : ILoadBalancer, new()
|
||||
{
|
||||
AddCustomLoadBalancer((provider, reRoute, serviceDiscoveryProvider) => new T());
|
||||
return this;
|
||||
}
|
||||
|
||||
public IOcelotBuilder AddCustomLoadBalancer<T>(Func<T> loadBalancerFactoryFunc)
|
||||
where T : ILoadBalancer
|
||||
{
|
||||
AddCustomLoadBalancer((provider, reRoute, serviceDiscoveryProvider) =>
|
||||
loadBalancerFactoryFunc());
|
||||
return this;
|
||||
}
|
||||
|
||||
public IOcelotBuilder AddCustomLoadBalancer<T>(Func<IServiceProvider, T> loadBalancerFactoryFunc)
|
||||
where T : ILoadBalancer
|
||||
{
|
||||
AddCustomLoadBalancer((provider, reRoute, serviceDiscoveryProvider) =>
|
||||
loadBalancerFactoryFunc(provider));
|
||||
return this;
|
||||
}
|
||||
|
||||
public IOcelotBuilder AddCustomLoadBalancer<T>(Func<DownstreamReRoute, IServiceDiscoveryProvider, T> loadBalancerFactoryFunc)
|
||||
where T : ILoadBalancer
|
||||
{
|
||||
AddCustomLoadBalancer((provider, reRoute, serviceDiscoveryProvider) =>
|
||||
loadBalancerFactoryFunc(reRoute, serviceDiscoveryProvider));
|
||||
return this;
|
||||
}
|
||||
|
||||
public IOcelotBuilder AddCustomLoadBalancer<T>(Func<IServiceProvider, DownstreamReRoute, IServiceDiscoveryProvider, T> loadBalancerFactoryFunc)
|
||||
where T : ILoadBalancer
|
||||
{
|
||||
Services.AddSingleton<ILoadBalancerCreator>(provider =>
|
||||
new DelegateInvokingLoadBalancerCreator<T>(
|
||||
(reRoute, serviceDiscoveryProvider) =>
|
||||
loadBalancerFactoryFunc(provider, reRoute, serviceDiscoveryProvider)));
|
||||
return this;
|
||||
}
|
||||
|
||||
private void AddSecurity()
|
||||
{
|
||||
Services.TryAddSingleton<ISecurityOptionsCreator, SecurityOptionsCreator>();
|
||||
|
@ -0,0 +1,20 @@
|
||||
namespace Ocelot.LoadBalancer.LoadBalancers
|
||||
{
|
||||
using System.Threading.Tasks;
|
||||
using Ocelot.Configuration;
|
||||
using Ocelot.Infrastructure;
|
||||
using Ocelot.ServiceDiscovery.Providers;
|
||||
|
||||
public class CookieStickySessionsCreator : ILoadBalancerCreator
|
||||
{
|
||||
public ILoadBalancer Create(DownstreamReRoute reRoute, IServiceDiscoveryProvider serviceProvider)
|
||||
{
|
||||
var loadBalancer = new RoundRobin(async () => await serviceProvider.Get());
|
||||
var bus = new InMemoryBus<StickySession>();
|
||||
return new CookieStickySessions(loadBalancer, reRoute.LoadBalancerOptions.Key,
|
||||
reRoute.LoadBalancerOptions.ExpiryInMs, bus);
|
||||
}
|
||||
|
||||
public string Type => nameof(CookieStickySessions);
|
||||
}
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
namespace Ocelot.LoadBalancer.LoadBalancers
|
||||
{
|
||||
using System;
|
||||
using Ocelot.Configuration;
|
||||
using Ocelot.ServiceDiscovery.Providers;
|
||||
|
||||
public class DelegateInvokingLoadBalancerCreator<T> : ILoadBalancerCreator
|
||||
where T : ILoadBalancer
|
||||
{
|
||||
private readonly Func<DownstreamReRoute, IServiceDiscoveryProvider, ILoadBalancer> _creatorFunc;
|
||||
|
||||
public DelegateInvokingLoadBalancerCreator(
|
||||
Func<DownstreamReRoute, IServiceDiscoveryProvider, ILoadBalancer> creatorFunc)
|
||||
{
|
||||
_creatorFunc = creatorFunc;
|
||||
}
|
||||
|
||||
public ILoadBalancer Create(DownstreamReRoute reRoute, IServiceDiscoveryProvider serviceProvider)
|
||||
{
|
||||
return _creatorFunc(reRoute, serviceProvider);
|
||||
}
|
||||
|
||||
public string Type => typeof(T).Name;
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
using Ocelot.Configuration;
|
||||
using Ocelot.ServiceDiscovery.Providers;
|
||||
|
||||
namespace Ocelot.LoadBalancer.LoadBalancers
|
||||
{
|
||||
public interface ILoadBalancerCreator
|
||||
{
|
||||
ILoadBalancer Create(DownstreamReRoute reRoute, IServiceDiscoveryProvider serviceProvider);
|
||||
string Type { get; }
|
||||
}
|
||||
}
|
@ -0,0 +1,15 @@
|
||||
namespace Ocelot.LoadBalancer.LoadBalancers
|
||||
{
|
||||
using Ocelot.Configuration;
|
||||
using Ocelot.ServiceDiscovery.Providers;
|
||||
|
||||
public class LeastConnectionCreator : ILoadBalancerCreator
|
||||
{
|
||||
public ILoadBalancer Create(DownstreamReRoute reRoute, IServiceDiscoveryProvider serviceProvider)
|
||||
{
|
||||
return new LeastConnection(async () => await serviceProvider.Get(), reRoute.ServiceName);
|
||||
}
|
||||
|
||||
public string Type => nameof(LeastConnection);
|
||||
}
|
||||
}
|
@ -1,47 +1,42 @@
|
||||
using Ocelot.Configuration;
|
||||
using Ocelot.Infrastructure;
|
||||
using Ocelot.Responses;
|
||||
using Ocelot.ServiceDiscovery;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Ocelot.LoadBalancer.LoadBalancers
|
||||
namespace Ocelot.LoadBalancer.LoadBalancers
|
||||
{
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Ocelot.Configuration;
|
||||
using Ocelot.Responses;
|
||||
using System.Threading.Tasks;
|
||||
using Ocelot.ServiceDiscovery;
|
||||
|
||||
public class LoadBalancerFactory : ILoadBalancerFactory
|
||||
{
|
||||
private readonly IServiceDiscoveryProviderFactory _serviceProviderFactory;
|
||||
private readonly IEnumerable<ILoadBalancerCreator> _loadBalancerCreators;
|
||||
|
||||
public LoadBalancerFactory(IServiceDiscoveryProviderFactory serviceProviderFactory)
|
||||
public LoadBalancerFactory(IServiceDiscoveryProviderFactory serviceProviderFactory, IEnumerable<ILoadBalancerCreator> loadBalancerCreators)
|
||||
{
|
||||
_serviceProviderFactory = serviceProviderFactory;
|
||||
_loadBalancerCreators = loadBalancerCreators;
|
||||
}
|
||||
|
||||
public async Task<Response<ILoadBalancer>> Get(DownstreamReRoute reRoute, ServiceProviderConfiguration config)
|
||||
public Task<Response<ILoadBalancer>> Get(DownstreamReRoute reRoute, ServiceProviderConfiguration config)
|
||||
{
|
||||
var response = _serviceProviderFactory.Get(config, reRoute);
|
||||
var serviceProviderFactoryResponse = _serviceProviderFactory.Get(config, reRoute);
|
||||
|
||||
if (response.IsError)
|
||||
Response<ILoadBalancer> response;
|
||||
if (serviceProviderFactoryResponse.IsError)
|
||||
{
|
||||
return new ErrorResponse<ILoadBalancer>(response.Errors);
|
||||
response = new ErrorResponse<ILoadBalancer>(serviceProviderFactoryResponse.Errors);
|
||||
}
|
||||
else
|
||||
{
|
||||
var serviceProvider = serviceProviderFactoryResponse.Data;
|
||||
var requestedType = reRoute.LoadBalancerOptions?.Type ?? nameof(NoLoadBalancer);
|
||||
var applicableCreator = _loadBalancerCreators.Single(c => c.Type == requestedType);
|
||||
var createdLoadBalancer = applicableCreator.Create(reRoute, serviceProvider);
|
||||
response = new OkResponse<ILoadBalancer>(createdLoadBalancer);
|
||||
}
|
||||
|
||||
var serviceProvider = response.Data;
|
||||
|
||||
switch (reRoute.LoadBalancerOptions?.Type)
|
||||
{
|
||||
case nameof(RoundRobin):
|
||||
return new OkResponse<ILoadBalancer>(new RoundRobin(async () => await serviceProvider.Get()));
|
||||
|
||||
case nameof(LeastConnection):
|
||||
return new OkResponse<ILoadBalancer>(new LeastConnection(async () => await serviceProvider.Get(), reRoute.ServiceName));
|
||||
|
||||
case nameof(CookieStickySessions):
|
||||
var loadBalancer = new RoundRobin(async () => await serviceProvider.Get());
|
||||
var bus = new InMemoryBus<StickySession>();
|
||||
return new OkResponse<ILoadBalancer>(new CookieStickySessions(loadBalancer, reRoute.LoadBalancerOptions.Key, reRoute.LoadBalancerOptions.ExpiryInMs, bus));
|
||||
|
||||
default:
|
||||
return new OkResponse<ILoadBalancer>(new NoLoadBalancer(async () => await serviceProvider.Get()));
|
||||
}
|
||||
return Task.FromResult(response);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,15 @@
|
||||
namespace Ocelot.LoadBalancer.LoadBalancers
|
||||
{
|
||||
using Ocelot.Configuration;
|
||||
using Ocelot.ServiceDiscovery.Providers;
|
||||
|
||||
public class NoLoadBalancerCreator : ILoadBalancerCreator
|
||||
{
|
||||
public ILoadBalancer Create(DownstreamReRoute reRoute, IServiceDiscoveryProvider serviceProvider)
|
||||
{
|
||||
return new NoLoadBalancer(async () => await serviceProvider.Get());
|
||||
}
|
||||
|
||||
public string Type => nameof(NoLoadBalancer);
|
||||
}
|
||||
}
|
@ -1,12 +1,12 @@
|
||||
using Ocelot.Middleware;
|
||||
using Ocelot.Responses;
|
||||
using Ocelot.Values;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Ocelot.LoadBalancer.LoadBalancers
|
||||
namespace Ocelot.LoadBalancer.LoadBalancers
|
||||
{
|
||||
using Ocelot.Middleware;
|
||||
using Ocelot.Responses;
|
||||
using Ocelot.Values;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
public class RoundRobin : ILoadBalancer
|
||||
{
|
||||
private readonly Func<Task<List<Service>>> _services;
|
||||
|
15
src/Ocelot/LoadBalancer/LoadBalancers/RoundRobinCreator.cs
Normal file
15
src/Ocelot/LoadBalancer/LoadBalancers/RoundRobinCreator.cs
Normal file
@ -0,0 +1,15 @@
|
||||
namespace Ocelot.LoadBalancer.LoadBalancers
|
||||
{
|
||||
using Ocelot.Configuration;
|
||||
using Ocelot.ServiceDiscovery.Providers;
|
||||
|
||||
public class RoundRobinCreator : ILoadBalancerCreator
|
||||
{
|
||||
public ILoadBalancer Create(DownstreamReRoute reRoute, IServiceDiscoveryProvider serviceProvider)
|
||||
{
|
||||
return new RoundRobin(async () => await serviceProvider.Get());
|
||||
}
|
||||
|
||||
public string Type => nameof(RoundRobin);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user