mirror of
https://github.com/nsnail/Ocelot.git
synced 2025-04-22 06:22:50 +08:00
plugged load balancer middleware into Ocelot pipeline, load balanced downstream host and port now used by url creator middleware
This commit is contained in:
parent
aef6507da3
commit
f285b0e0ad
@ -6,6 +6,7 @@ namespace Ocelot.Configuration.Builder
|
|||||||
{
|
{
|
||||||
public class ReRouteBuilder
|
public class ReRouteBuilder
|
||||||
{
|
{
|
||||||
|
private string _loadBalancerKey;
|
||||||
private string _downstreamPathTemplate;
|
private string _downstreamPathTemplate;
|
||||||
private string _upstreamTemplate;
|
private string _upstreamTemplate;
|
||||||
private string _upstreamTemplatePattern;
|
private string _upstreamTemplatePattern;
|
||||||
@ -199,6 +200,12 @@ namespace Ocelot.Configuration.Builder
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ReRouteBuilder WithLoadBalancerKey(string loadBalancerKey)
|
||||||
|
{
|
||||||
|
_loadBalancerKey = loadBalancerKey;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public ReRoute Build()
|
public ReRoute Build()
|
||||||
{
|
{
|
||||||
return new ReRoute(new DownstreamPathTemplate(_downstreamPathTemplate), _upstreamTemplate, _upstreamHttpMethod, _upstreamTemplatePattern,
|
return new ReRoute(new DownstreamPathTemplate(_downstreamPathTemplate), _upstreamTemplate, _upstreamHttpMethod, _upstreamTemplatePattern,
|
||||||
@ -206,7 +213,7 @@ namespace Ocelot.Configuration.Builder
|
|||||||
_requireHttps, _additionalScopes, _scopeSecret), _configHeaderExtractorProperties, _claimToClaims, _routeClaimRequirement,
|
_requireHttps, _additionalScopes, _scopeSecret), _configHeaderExtractorProperties, _claimToClaims, _routeClaimRequirement,
|
||||||
_isAuthorised, _claimToQueries, _requestIdHeaderKey, _isCached, _fileCacheOptions, _serviceName,
|
_isAuthorised, _claimToQueries, _requestIdHeaderKey, _isCached, _fileCacheOptions, _serviceName,
|
||||||
_useServiceDiscovery, _serviceDiscoveryAddress, _serviceDiscoveryProvider, _downstreamScheme, _loadBalancer,
|
_useServiceDiscovery, _serviceDiscoveryAddress, _serviceDiscoveryProvider, _downstreamScheme, _loadBalancer,
|
||||||
_downstreamHost, _dsPort);
|
_downstreamHost, _dsPort, _loadBalancerKey);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -104,6 +104,9 @@ namespace Ocelot.Configuration.Creator
|
|||||||
&& !string.IsNullOrEmpty(globalConfiguration?.ServiceDiscoveryProvider?.Address)
|
&& !string.IsNullOrEmpty(globalConfiguration?.ServiceDiscoveryProvider?.Address)
|
||||||
&& !string.IsNullOrEmpty(globalConfiguration?.ServiceDiscoveryProvider?.Provider);
|
&& !string.IsNullOrEmpty(globalConfiguration?.ServiceDiscoveryProvider?.Provider);
|
||||||
|
|
||||||
|
//note - not sure if this is the correct key, but this is probably the only unique key i can think of given my poor brain
|
||||||
|
var loadBalancerKey = $"{fileReRoute.UpstreamTemplate}{fileReRoute.UpstreamHttpMethod}";
|
||||||
|
|
||||||
ReRoute reRoute;
|
ReRoute reRoute;
|
||||||
|
|
||||||
if (isAuthenticated)
|
if (isAuthenticated)
|
||||||
@ -124,7 +127,7 @@ namespace Ocelot.Configuration.Creator
|
|||||||
requestIdKey, isCached, new CacheOptions(fileReRoute.FileCacheOptions.TtlSeconds),
|
requestIdKey, isCached, new CacheOptions(fileReRoute.FileCacheOptions.TtlSeconds),
|
||||||
fileReRoute.ServiceName, useServiceDiscovery, globalConfiguration?.ServiceDiscoveryProvider?.Provider,
|
fileReRoute.ServiceName, useServiceDiscovery, globalConfiguration?.ServiceDiscoveryProvider?.Provider,
|
||||||
globalConfiguration?.ServiceDiscoveryProvider?.Address, fileReRoute.DownstreamScheme,
|
globalConfiguration?.ServiceDiscoveryProvider?.Address, fileReRoute.DownstreamScheme,
|
||||||
fileReRoute.LoadBalancer, fileReRoute.DownstreamHost, fileReRoute.DownstreamPort);
|
fileReRoute.LoadBalancer, fileReRoute.DownstreamHost, fileReRoute.DownstreamPort,loadBalancerKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
reRoute = new ReRoute(new DownstreamPathTemplate(fileReRoute.DownstreamPathTemplate), fileReRoute.UpstreamTemplate,
|
reRoute = new ReRoute(new DownstreamPathTemplate(fileReRoute.DownstreamPathTemplate), fileReRoute.UpstreamTemplate,
|
||||||
@ -134,11 +137,10 @@ namespace Ocelot.Configuration.Creator
|
|||||||
requestIdKey, isCached, new CacheOptions(fileReRoute.FileCacheOptions.TtlSeconds),
|
requestIdKey, isCached, new CacheOptions(fileReRoute.FileCacheOptions.TtlSeconds),
|
||||||
fileReRoute.ServiceName, useServiceDiscovery, globalConfiguration?.ServiceDiscoveryProvider?.Provider,
|
fileReRoute.ServiceName, useServiceDiscovery, globalConfiguration?.ServiceDiscoveryProvider?.Provider,
|
||||||
globalConfiguration?.ServiceDiscoveryProvider?.Address, fileReRoute.DownstreamScheme,
|
globalConfiguration?.ServiceDiscoveryProvider?.Address, fileReRoute.DownstreamScheme,
|
||||||
fileReRoute.LoadBalancer, fileReRoute.DownstreamHost, fileReRoute.DownstreamPort);
|
fileReRoute.LoadBalancer, fileReRoute.DownstreamHost, fileReRoute.DownstreamPort,loadBalancerKey);
|
||||||
|
|
||||||
var loadBalancer = _loadBalanceFactory.Get(reRoute);
|
var loadBalancer = _loadBalanceFactory.Get(reRoute);
|
||||||
//todo - not sure if this is the correct key, but this is probably the only unique key i can think of
|
_loadBalancerHouse.Add(reRoute.LoadBalancerKey, loadBalancer);
|
||||||
_loadBalancerHouse.Add($"{fileReRoute.UpstreamTemplate}{fileReRoute.UpstreamHttpMethod}", loadBalancer);
|
|
||||||
return reRoute;
|
return reRoute;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,8 +11,9 @@ namespace Ocelot.Configuration
|
|||||||
List<ClaimToThing> claimsToClaims, Dictionary<string, string> routeClaimsRequirement, bool isAuthorised, List<ClaimToThing> claimsToQueries,
|
List<ClaimToThing> claimsToClaims, Dictionary<string, string> routeClaimsRequirement, bool isAuthorised, List<ClaimToThing> claimsToQueries,
|
||||||
string requestIdKey, bool isCached, CacheOptions fileCacheOptions, string serviceName, bool useServiceDiscovery,
|
string requestIdKey, bool isCached, CacheOptions fileCacheOptions, string serviceName, bool useServiceDiscovery,
|
||||||
string serviceDiscoveryProvider, string serviceDiscoveryAddress,
|
string serviceDiscoveryProvider, string serviceDiscoveryAddress,
|
||||||
string downstreamScheme, string loadBalancer, string downstreamHost, int downstreamPort)
|
string downstreamScheme, string loadBalancer, string downstreamHost, int downstreamPort, string loadBalancerKey)
|
||||||
{
|
{
|
||||||
|
LoadBalancerKey = loadBalancerKey;
|
||||||
LoadBalancer = loadBalancer;
|
LoadBalancer = loadBalancer;
|
||||||
DownstreamHost = downstreamHost;
|
DownstreamHost = downstreamHost;
|
||||||
DownstreamPort = downstreamPort;
|
DownstreamPort = downstreamPort;
|
||||||
@ -39,6 +40,7 @@ namespace Ocelot.Configuration
|
|||||||
ServiceDiscoveryAddress = serviceDiscoveryAddress;
|
ServiceDiscoveryAddress = serviceDiscoveryAddress;
|
||||||
DownstreamScheme = downstreamScheme;
|
DownstreamScheme = downstreamScheme;
|
||||||
}
|
}
|
||||||
|
public string LoadBalancerKey {get;private set;}
|
||||||
public DownstreamPathTemplate DownstreamPathTemplate { get; private set; }
|
public DownstreamPathTemplate DownstreamPathTemplate { get; private set; }
|
||||||
public string UpstreamTemplate { get; private set; }
|
public string UpstreamTemplate { get; private set; }
|
||||||
public string UpstreamTemplatePattern { get; private set; }
|
public string UpstreamTemplatePattern { get; private set; }
|
||||||
|
@ -47,15 +47,12 @@ namespace Ocelot.DownstreamUrlCreator.Middleware
|
|||||||
|
|
||||||
var dsScheme = DownstreamRoute.ReRoute.DownstreamScheme;
|
var dsScheme = DownstreamRoute.ReRoute.DownstreamScheme;
|
||||||
|
|
||||||
//todo - get this out of scoped data repo?
|
var dsHostAndPort = HostAndPort;
|
||||||
var dsHostAndPort = new HostAndPort(DownstreamRoute.ReRoute.DownstreamHost,
|
|
||||||
DownstreamRoute.ReRoute.DownstreamPort);
|
|
||||||
|
|
||||||
var dsUrl = _urlBuilder.Build(dsPath.Data.Value, dsScheme, dsHostAndPort);
|
var dsUrl = _urlBuilder.Build(dsPath.Data.Value, dsScheme, dsHostAndPort);
|
||||||
|
|
||||||
if (dsUrl.IsError)
|
if (dsUrl.IsError)
|
||||||
{
|
{
|
||||||
//todo - release the lb connection?
|
|
||||||
_logger.LogDebug("IUrlBuilder returned an error, setting pipeline error");
|
_logger.LogDebug("IUrlBuilder returned an error, setting pipeline error");
|
||||||
|
|
||||||
SetPipelineError(dsUrl.Errors);
|
SetPipelineError(dsUrl.Errors);
|
||||||
@ -70,8 +67,6 @@ namespace Ocelot.DownstreamUrlCreator.Middleware
|
|||||||
|
|
||||||
await _next.Invoke(context);
|
await _next.Invoke(context);
|
||||||
|
|
||||||
//todo - release the lb connection?
|
|
||||||
|
|
||||||
_logger.LogDebug("succesfully called next middleware");
|
_logger.LogDebug("succesfully called next middleware");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -31,26 +31,32 @@ namespace Ocelot.LoadBalancer.Middleware
|
|||||||
{
|
{
|
||||||
_logger.LogDebug("started calling load balancing middleware");
|
_logger.LogDebug("started calling load balancing middleware");
|
||||||
|
|
||||||
var loadBalancer = _loadBalancerHouse.Get($"{DownstreamRoute.ReRoute.UpstreamTemplate}{DownstreamRoute.ReRoute.UpstreamHttpMethod}");
|
var loadBalancer = _loadBalancerHouse.Get(DownstreamRoute.ReRoute.LoadBalancerKey);
|
||||||
//todo check reponse and return error
|
if(loadBalancer.IsError)
|
||||||
|
{
|
||||||
|
//set errors and return
|
||||||
|
}
|
||||||
|
|
||||||
var response = loadBalancer.Data.Lease();
|
var hostAndPort = loadBalancer.Data.Lease();
|
||||||
//todo check reponse and return error
|
if(hostAndPort.IsError)
|
||||||
|
{
|
||||||
|
//set errors and return
|
||||||
|
}
|
||||||
|
|
||||||
|
SetHostAndPortForThisRequest(hostAndPort.Data);
|
||||||
|
|
||||||
SetHostAndPortForThisRequest(response.Data);
|
|
||||||
_logger.LogDebug("calling next middleware");
|
_logger.LogDebug("calling next middleware");
|
||||||
|
|
||||||
//todo - try next middleware if we get an exception make sure we release
|
|
||||||
//the host and port? Not sure if this is the way to go but we shall see!
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await _next.Invoke(context);
|
await _next.Invoke(context);
|
||||||
|
|
||||||
loadBalancer.Data.Release(response.Data);
|
loadBalancer.Data.Release(hostAndPort.Data);
|
||||||
}
|
}
|
||||||
catch (Exception)
|
catch (Exception)
|
||||||
{
|
{
|
||||||
loadBalancer.Data.Release(response.Data);
|
loadBalancer.Data.Release(hostAndPort.Data);
|
||||||
|
_logger.LogDebug("error calling next middleware, exception will be thrown to global handler");
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@ namespace Ocelot.LoadBalancer.Middleware
|
|||||||
{
|
{
|
||||||
public static class LoadBalancingMiddlewareExtensions
|
public static class LoadBalancingMiddlewareExtensions
|
||||||
{
|
{
|
||||||
public static IApplicationBuilder UseLoadBalancingMiddlewareExtensions(this IApplicationBuilder builder)
|
public static IApplicationBuilder UseLoadBalancingMiddleware(this IApplicationBuilder builder)
|
||||||
{
|
{
|
||||||
return builder.UseMiddleware<LoadBalancingMiddleware>();
|
return builder.UseMiddleware<LoadBalancingMiddleware>();
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,7 @@ namespace Ocelot.Middleware
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Authorisation.Middleware;
|
using Authorisation.Middleware;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using Ocelot.LoadBalancer.Middleware;
|
||||||
|
|
||||||
public static class OcelotMiddlewareExtensions
|
public static class OcelotMiddlewareExtensions
|
||||||
{
|
{
|
||||||
@ -98,6 +99,9 @@ namespace Ocelot.Middleware
|
|||||||
// Now we can run any query string transformation logic
|
// Now we can run any query string transformation logic
|
||||||
builder.UseQueryStringBuilderMiddleware();
|
builder.UseQueryStringBuilderMiddleware();
|
||||||
|
|
||||||
|
// Get the load balancer for this request
|
||||||
|
builder.UseLoadBalancingMiddleware();
|
||||||
|
|
||||||
// This takes the downstream route we retrieved earlier and replaces any placeholders with the variables that should be used
|
// This takes the downstream route we retrieved earlier and replaces any placeholders with the variables that should be used
|
||||||
builder.UseDownstreamUrlCreatorMiddleware();
|
builder.UseDownstreamUrlCreatorMiddleware();
|
||||||
|
|
||||||
|
@ -36,6 +36,7 @@ namespace Ocelot.UnitTests.DownstreamUrlCreator
|
|||||||
private HttpResponseMessage _result;
|
private HttpResponseMessage _result;
|
||||||
private OkResponse<DownstreamPath> _downstreamPath;
|
private OkResponse<DownstreamPath> _downstreamPath;
|
||||||
private OkResponse<DownstreamUrl> _downstreamUrl;
|
private OkResponse<DownstreamUrl> _downstreamUrl;
|
||||||
|
private HostAndPort _hostAndPort;
|
||||||
|
|
||||||
public DownstreamUrlCreatorMiddlewareTests()
|
public DownstreamUrlCreatorMiddlewareTests()
|
||||||
{
|
{
|
||||||
@ -69,14 +70,25 @@ namespace Ocelot.UnitTests.DownstreamUrlCreator
|
|||||||
[Fact]
|
[Fact]
|
||||||
public void should_call_dependencies_correctly()
|
public void should_call_dependencies_correctly()
|
||||||
{
|
{
|
||||||
|
var hostAndPort = new HostAndPort("127.0.0.1", 80);
|
||||||
|
|
||||||
this.Given(x => x.GivenTheDownStreamRouteIs(new DownstreamRoute(new List<UrlPathPlaceholderNameAndValue>(), new ReRouteBuilder().WithDownstreamPathTemplate("any old string").Build())))
|
this.Given(x => x.GivenTheDownStreamRouteIs(new DownstreamRoute(new List<UrlPathPlaceholderNameAndValue>(), new ReRouteBuilder().WithDownstreamPathTemplate("any old string").Build())))
|
||||||
|
.And(x => x.GivenTheHostAndPortIs(hostAndPort))
|
||||||
.And(x => x.TheUrlReplacerReturns("/api/products/1"))
|
.And(x => x.TheUrlReplacerReturns("/api/products/1"))
|
||||||
.And(x => x.TheUrlBuilderReturns("http://www.bbc.co.uk/api/products/1"))
|
.And(x => x.TheUrlBuilderReturns("http://127.0.0.1:80/api/products/1"))
|
||||||
.When(x => x.WhenICallTheMiddleware())
|
.When(x => x.WhenICallTheMiddleware())
|
||||||
.Then(x => x.ThenTheScopedDataRepositoryIsCalledCorrectly())
|
.Then(x => x.ThenTheScopedDataRepositoryIsCalledCorrectly())
|
||||||
.BDDfy();
|
.BDDfy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void GivenTheHostAndPortIs(HostAndPort hostAndPort)
|
||||||
|
{
|
||||||
|
_hostAndPort = hostAndPort;
|
||||||
|
_scopedRepository
|
||||||
|
.Setup(x => x.Get<HostAndPort>("HostAndPort"))
|
||||||
|
.Returns(new OkResponse<HostAndPort>(_hostAndPort));
|
||||||
|
}
|
||||||
|
|
||||||
private void TheUrlBuilderReturns(string dsUrl)
|
private void TheUrlBuilderReturns(string dsUrl)
|
||||||
{
|
{
|
||||||
_downstreamUrl = new OkResponse<DownstreamUrl>(new DownstreamUrl(dsUrl));
|
_downstreamUrl = new OkResponse<DownstreamUrl>(new DownstreamUrl(dsUrl));
|
||||||
|
@ -54,7 +54,7 @@ namespace Ocelot.UnitTests.LoadBalancer
|
|||||||
.UseUrls(_url)
|
.UseUrls(_url)
|
||||||
.Configure(app =>
|
.Configure(app =>
|
||||||
{
|
{
|
||||||
app.UseLoadBalancingMiddlewareExtensions();
|
app.UseLoadBalancingMiddleware();
|
||||||
});
|
});
|
||||||
|
|
||||||
_server = new TestServer(builder);
|
_server = new TestServer(builder);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user