Feature/poll consul (#392)

* WIP - implement a consul service discovery poller, lots of shared code with existing, refactor next and a todo in the docs to finish

* #374 implement polling for consul as option

* #374 updated docs to remove todo

* #374 fixed failing unit test

* #374 fixed failing unit test

* #374 fixed failing acceptance test
This commit is contained in:
Tom Pallister
2018-06-12 00:58:08 +03:00
committed by GitHub
parent 14308ff5fb
commit 0f2a9c1d0d
12 changed files with 649 additions and 369 deletions

View File

@ -7,6 +7,7 @@ namespace Ocelot.Configuration.Builder
private string _type;
private string _token;
private string _configurationKey;
private int _pollingInterval;
public ServiceProviderConfigurationBuilder WithHost(string serviceDiscoveryProviderHost)
{
@ -38,9 +39,15 @@ namespace Ocelot.Configuration.Builder
return this;
}
public ServiceProviderConfigurationBuilder WithPollingInterval(int pollingInterval)
{
_pollingInterval = pollingInterval;
return this;
}
public ServiceProviderConfiguration Build()
{
return new ServiceProviderConfiguration(_type, _serviceDiscoveryProviderHost, _serviceDiscoveryProviderPort, _token, _configurationKey);
return new ServiceProviderConfiguration(_type, _serviceDiscoveryProviderHost, _serviceDiscoveryProviderPort, _token, _configurationKey, _pollingInterval);
}
}
}

View File

@ -9,6 +9,7 @@ namespace Ocelot.Configuration.Creator
{
var port = globalConfiguration?.ServiceDiscoveryProvider?.Port ?? 0;
var host = globalConfiguration?.ServiceDiscoveryProvider?.Host ?? "consul";
var pollingInterval = globalConfiguration?.ServiceDiscoveryProvider?.PollingInterval ?? 0;
return new ServiceProviderConfigurationBuilder()
.WithHost(host)
@ -16,6 +17,7 @@ namespace Ocelot.Configuration.Creator
.WithType(globalConfiguration?.ServiceDiscoveryProvider?.Type)
.WithToken(globalConfiguration?.ServiceDiscoveryProvider?.Token)
.WithConfigurationKey(globalConfiguration?.ServiceDiscoveryProvider?.ConfigurationKey)
.WithPollingInterval(pollingInterval)
.Build();
}
}

View File

@ -7,5 +7,6 @@ namespace Ocelot.Configuration.File
public string Type { get; set; }
public string Token { get; set; }
public string ConfigurationKey { get; set; }
public int PollingInterval { get; set; }
}
}

View File

@ -2,13 +2,14 @@
{
public class ServiceProviderConfiguration
{
public ServiceProviderConfiguration(string type, string host, int port, string token, string configurationKey)
public ServiceProviderConfiguration(string type, string host, int port, string token, string configurationKey, int pollingInterval)
{
ConfigurationKey = configurationKey;
Host = host;
Port = port;
Token = token;
Type = type;
PollingInterval = pollingInterval;
}
public string Host { get; }
@ -16,5 +17,6 @@
public string Type { get; }
public string Token { get; }
public string ConfigurationKey { get; }
public int PollingInterval { get; }
}
}

View File

@ -0,0 +1,56 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Consul;
using Ocelot.Infrastructure.Consul;
using Ocelot.Infrastructure.Extensions;
using Ocelot.Logging;
using Ocelot.ServiceDiscovery.Configuration;
using Ocelot.Values;
namespace Ocelot.ServiceDiscovery.Providers
{
public class PollingConsulServiceDiscoveryProvider : IServiceDiscoveryProvider
{
private readonly IOcelotLogger _logger;
private readonly IServiceDiscoveryProvider _consulServiceDiscoveryProvider;
private readonly Timer _timer;
private bool _polling;
private List<Service> _services;
private string _keyOfServiceInConsul;
public PollingConsulServiceDiscoveryProvider(int pollingInterval, string keyOfServiceInConsul, IOcelotLoggerFactory factory, IServiceDiscoveryProvider consulServiceDiscoveryProvider)
{;
_logger = factory.CreateLogger<PollingConsulServiceDiscoveryProvider>();
_keyOfServiceInConsul = keyOfServiceInConsul;
_consulServiceDiscoveryProvider = consulServiceDiscoveryProvider;
_services = new List<Service>();
_timer = new Timer(async x =>
{
if(_polling)
{
return;
}
_polling = true;
await Poll();
_polling = false;
}, null, pollingInterval, pollingInterval);
}
public Task<List<Service>> Get()
{
return Task.FromResult(_services);
}
private async Task Poll()
{
_services = await _consulServiceDiscoveryProvider.Get();
}
}
}

View File

@ -1,62 +1,70 @@
using System.Collections.Generic;
using Ocelot.Configuration;
using Ocelot.Infrastructure.Consul;
using Ocelot.Logging;
using Ocelot.ServiceDiscovery.Configuration;
using Ocelot.ServiceDiscovery.Providers;
using Ocelot.Values;
namespace Ocelot.ServiceDiscovery
using System.Collections.Generic;
using Ocelot.Configuration;
using Ocelot.Infrastructure.Consul;
using Ocelot.Logging;
using Ocelot.ServiceDiscovery.Configuration;
using Ocelot.ServiceDiscovery.Providers;
using Ocelot.Values;
namespace Ocelot.ServiceDiscovery
{
using Steeltoe.Common.Discovery;
public class ServiceDiscoveryProviderFactory : IServiceDiscoveryProviderFactory
{
private readonly IOcelotLoggerFactory _factory;
private readonly IConsulClientFactory _consulFactory;
private readonly IDiscoveryClient _eurekaClient;
public ServiceDiscoveryProviderFactory(IOcelotLoggerFactory factory, IConsulClientFactory consulFactory, IDiscoveryClient eurekaClient)
{
_factory = factory;
_consulFactory = consulFactory;
_eurekaClient = eurekaClient;
}
public IServiceDiscoveryProvider Get(ServiceProviderConfiguration serviceConfig, DownstreamReRoute reRoute)
{
if (reRoute.UseServiceDiscovery)
{
return GetServiceDiscoveryProvider(serviceConfig, reRoute.ServiceName);
}
var services = new List<Service>();
foreach (var downstreamAddress in reRoute.DownstreamAddresses)
{
var service = new Service(reRoute.ServiceName, new ServiceHostAndPort(downstreamAddress.Host, downstreamAddress.Port), string.Empty, string.Empty, new string[0]);
services.Add(service);
}
return new ConfigurationServiceProvider(services);
}
private IServiceDiscoveryProvider GetServiceDiscoveryProvider(ServiceProviderConfiguration serviceConfig, string serviceName)
{
if (serviceConfig.Type?.ToLower() == "servicefabric")
{
var config = new ServiceFabricConfiguration(serviceConfig.Host, serviceConfig.Port, serviceName);
return new ServiceFabricServiceDiscoveryProvider(config);
}
if (serviceConfig.Type?.ToLower() == "eureka")
{
return new EurekaServiceDiscoveryProvider(serviceName, _eurekaClient);
}
var consulRegistryConfiguration = new ConsulRegistryConfiguration(serviceConfig.Host, serviceConfig.Port, serviceName, serviceConfig.Token);
return new ConsulServiceDiscoveryProvider(consulRegistryConfiguration, _factory, _consulFactory);
}
}
}
public class ServiceDiscoveryProviderFactory : IServiceDiscoveryProviderFactory
{
private readonly IOcelotLoggerFactory _factory;
private readonly IConsulClientFactory _consulFactory;
private readonly IDiscoveryClient _eurekaClient;
public ServiceDiscoveryProviderFactory(IOcelotLoggerFactory factory, IConsulClientFactory consulFactory, IDiscoveryClient eurekaClient)
{
_factory = factory;
_consulFactory = consulFactory;
_eurekaClient = eurekaClient;
}
public IServiceDiscoveryProvider Get(ServiceProviderConfiguration serviceConfig, DownstreamReRoute reRoute)
{
if (reRoute.UseServiceDiscovery)
{
return GetServiceDiscoveryProvider(serviceConfig, reRoute.ServiceName);
}
var services = new List<Service>();
foreach (var downstreamAddress in reRoute.DownstreamAddresses)
{
var service = new Service(reRoute.ServiceName, new ServiceHostAndPort(downstreamAddress.Host, downstreamAddress.Port), string.Empty, string.Empty, new string[0]);
services.Add(service);
}
return new ConfigurationServiceProvider(services);
}
private IServiceDiscoveryProvider GetServiceDiscoveryProvider(ServiceProviderConfiguration serviceConfig, string serviceName)
{
if (serviceConfig.Type?.ToLower() == "servicefabric")
{
var config = new ServiceFabricConfiguration(serviceConfig.Host, serviceConfig.Port, serviceName);
return new ServiceFabricServiceDiscoveryProvider(config);
}
if (serviceConfig.Type?.ToLower() == "eureka")
{
return new EurekaServiceDiscoveryProvider(serviceName, _eurekaClient);
}
var consulRegistryConfiguration = new ConsulRegistryConfiguration(serviceConfig.Host, serviceConfig.Port, serviceName, serviceConfig.Token);
var consulServiceDiscoveryProvider = new ConsulServiceDiscoveryProvider(consulRegistryConfiguration, _factory, _consulFactory);
if (serviceConfig.Type?.ToLower() == "pollconsul")
{
return new PollingConsulServiceDiscoveryProvider(serviceConfig.PollingInterval, consulRegistryConfiguration.KeyOfServiceInConsul, _factory, consulServiceDiscoveryProvider);
}
return consulServiceDiscoveryProvider;
}
}
}