mirror of
https://github.com/nsnail/Ocelot.git
synced 2025-06-19 06:18:16 +08:00
This commit is contained in:
@ -1,97 +0,0 @@
|
||||
namespace Ocelot.Configuration.Repository
|
||||
{
|
||||
using System;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Consul;
|
||||
using Newtonsoft.Json;
|
||||
using Ocelot.Configuration.File;
|
||||
using Ocelot.Infrastructure.Consul;
|
||||
using Ocelot.Logging;
|
||||
using Ocelot.Responses;
|
||||
using Ocelot.ServiceDiscovery.Configuration;
|
||||
|
||||
public class ConsulFileConfigurationRepository : IFileConfigurationRepository
|
||||
{
|
||||
private readonly IConsulClient _consul;
|
||||
private readonly string _configurationKey;
|
||||
private readonly Cache.IOcelotCache<FileConfiguration> _cache;
|
||||
private readonly IOcelotLogger _logger;
|
||||
|
||||
public ConsulFileConfigurationRepository(
|
||||
Cache.IOcelotCache<FileConfiguration> cache,
|
||||
IInternalConfigurationRepository repo,
|
||||
IConsulClientFactory factory,
|
||||
IOcelotLoggerFactory loggerFactory)
|
||||
{
|
||||
_logger = loggerFactory.CreateLogger<ConsulFileConfigurationRepository>();
|
||||
_cache = cache;
|
||||
|
||||
var internalConfig = repo.Get();
|
||||
|
||||
_configurationKey = "InternalConfiguration";
|
||||
|
||||
string token = null;
|
||||
|
||||
if (!internalConfig.IsError)
|
||||
{
|
||||
token = internalConfig.Data.ServiceProviderConfiguration.Token;
|
||||
_configurationKey = !string.IsNullOrEmpty(internalConfig.Data.ServiceProviderConfiguration.ConfigurationKey) ?
|
||||
internalConfig.Data.ServiceProviderConfiguration.ConfigurationKey : _configurationKey;
|
||||
}
|
||||
|
||||
var config = new ConsulRegistryConfiguration(internalConfig.Data.ServiceProviderConfiguration.Host,
|
||||
internalConfig.Data.ServiceProviderConfiguration.Port, _configurationKey, token);
|
||||
|
||||
_consul = factory.Get(config);
|
||||
}
|
||||
|
||||
public async Task<Response<FileConfiguration>> Get()
|
||||
{
|
||||
var config = _cache.Get(_configurationKey, _configurationKey);
|
||||
|
||||
if (config != null)
|
||||
{
|
||||
return new OkResponse<FileConfiguration>(config);
|
||||
}
|
||||
|
||||
var queryResult = await _consul.KV.Get(_configurationKey);
|
||||
|
||||
if (queryResult.Response == null)
|
||||
{
|
||||
return new OkResponse<FileConfiguration>(null);
|
||||
}
|
||||
|
||||
var bytes = queryResult.Response.Value;
|
||||
|
||||
var json = Encoding.UTF8.GetString(bytes);
|
||||
|
||||
var consulConfig = JsonConvert.DeserializeObject<FileConfiguration>(json);
|
||||
|
||||
return new OkResponse<FileConfiguration>(consulConfig);
|
||||
}
|
||||
|
||||
public async Task<Response> Set(FileConfiguration ocelotConfiguration)
|
||||
{
|
||||
var json = JsonConvert.SerializeObject(ocelotConfiguration, Formatting.Indented);
|
||||
|
||||
var bytes = Encoding.UTF8.GetBytes(json);
|
||||
|
||||
var kvPair = new KVPair(_configurationKey)
|
||||
{
|
||||
Value = bytes
|
||||
};
|
||||
|
||||
var result = await _consul.KV.Put(kvPair);
|
||||
|
||||
if (result.Response)
|
||||
{
|
||||
_cache.AddAndDelete(_configurationKey, ocelotConfiguration, TimeSpan.FromSeconds(3), _configurationKey);
|
||||
|
||||
return new OkResponse();
|
||||
}
|
||||
|
||||
return new ErrorResponse(new UnableToSetConfigInConsulError($"Unable to set FileConfiguration in consul, response status code from consul was {result.StatusCode}"));
|
||||
}
|
||||
}
|
||||
}
|
@ -10,8 +10,8 @@ namespace Ocelot.DependencyInjection
|
||||
public interface IOcelotBuilder
|
||||
{
|
||||
IServiceCollection Services { get; }
|
||||
|
||||
IConfiguration Configuration { get; }
|
||||
IOcelotBuilder AddStoreOcelotConfigurationInConsul();
|
||||
|
||||
IOcelotAdministrationBuilder AddAdministration(string path, string secret);
|
||||
|
||||
@ -22,6 +22,7 @@ namespace Ocelot.DependencyInjection
|
||||
|
||||
IOcelotBuilder AddSingletonDefinedAggregator<T>()
|
||||
where T : class, IDefinedAggregator;
|
||||
|
||||
IOcelotBuilder AddTransientDefinedAggregator<T>()
|
||||
where T : class, IDefinedAggregator;
|
||||
}
|
||||
|
@ -40,7 +40,6 @@ namespace Ocelot.DependencyInjection
|
||||
using Microsoft.Extensions.DependencyInjection.Extensions;
|
||||
using System.Net.Http;
|
||||
using Ocelot.Infrastructure;
|
||||
using Ocelot.Infrastructure.Consul;
|
||||
using Ocelot.Middleware.Multiplexer;
|
||||
using ServiceDiscovery.Providers;
|
||||
using Steeltoe.Common.Discovery;
|
||||
@ -148,7 +147,6 @@ namespace Ocelot.DependencyInjection
|
||||
Services.TryAddSingleton<IFileConfigurationPollerOptions, InMemoryFileConfigurationPollerOptions>();
|
||||
Services.TryAddSingleton<IAddHeadersToResponse, AddHeadersToResponse>();
|
||||
Services.TryAddSingleton<IPlaceholders, Placeholders>();
|
||||
Services.TryAddSingleton<IConsulClientFactory, ConsulClientFactory>();
|
||||
Services.TryAddSingleton<IResponseAggregatorFactory, InMemoryResponseAggregatorFactory>();
|
||||
Services.TryAddSingleton<IDefinedAggregatorProvider, ServiceLocatorDefinedAggregatorProvider>();
|
||||
Services.TryAddSingleton<IDownstreamRequestCreator, DownstreamRequestCreator>();
|
||||
@ -217,13 +215,6 @@ namespace Ocelot.DependencyInjection
|
||||
return this;
|
||||
}
|
||||
|
||||
public IOcelotBuilder AddStoreOcelotConfigurationInConsul()
|
||||
{
|
||||
Services.AddHostedService<FileConfigurationPoller>();
|
||||
Services.AddSingleton<IFileConfigurationRepository, ConsulFileConfigurationRepository>();
|
||||
return this;
|
||||
}
|
||||
|
||||
private void AddIdentityServer(Action<IdentityServerAuthenticationOptions> configOptions)
|
||||
{
|
||||
Services
|
||||
|
@ -1,22 +0,0 @@
|
||||
using System;
|
||||
using Consul;
|
||||
using Ocelot.ServiceDiscovery.Configuration;
|
||||
|
||||
namespace Ocelot.Infrastructure.Consul
|
||||
{
|
||||
public class ConsulClientFactory : IConsulClientFactory
|
||||
{
|
||||
public IConsulClient Get(ConsulRegistryConfiguration config)
|
||||
{
|
||||
return new ConsulClient(c =>
|
||||
{
|
||||
c.Address = new Uri($"http://{config.Host}:{config.Port}");
|
||||
|
||||
if (!string.IsNullOrEmpty(config?.Token))
|
||||
{
|
||||
c.Token = config.Token;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
@ -1,10 +0,0 @@
|
||||
using Consul;
|
||||
using Ocelot.ServiceDiscovery.Configuration;
|
||||
|
||||
namespace Ocelot.Infrastructure.Consul
|
||||
{
|
||||
public interface IConsulClientFactory
|
||||
{
|
||||
IConsulClient Get(ConsulRegistryConfiguration config);
|
||||
}
|
||||
}
|
@ -242,7 +242,8 @@
|
||||
|
||||
private static bool UsingConsul(IFileConfigurationRepository fileConfigRepo)
|
||||
{
|
||||
return fileConfigRepo.GetType() == typeof(ConsulFileConfigurationRepository);
|
||||
//todo - remove coupling by string
|
||||
return fileConfigRepo.GetType().Name == "ConsulFileConfigurationRepository";
|
||||
}
|
||||
|
||||
private static void CreateAdministrationArea(IApplicationBuilder builder, IInternalConfiguration configuration)
|
||||
|
@ -46,7 +46,6 @@
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="System.Text.RegularExpressions" Version="4.3.0" />
|
||||
<PackageReference Include="Consul" Version="0.7.2.5" />
|
||||
<PackageReference Include="Polly" Version="6.0.1" />
|
||||
<PackageReference Include="IdentityServer4" Version="2.2.0" />
|
||||
<PackageReference Include="Pivotal.Discovery.ClientCore" Version="2.0.1" />
|
||||
|
@ -1,18 +0,0 @@
|
||||
namespace Ocelot.ServiceDiscovery.Configuration
|
||||
{
|
||||
public class ConsulRegistryConfiguration
|
||||
{
|
||||
public ConsulRegistryConfiguration(string host, int port, string keyOfServiceInConsul, string token)
|
||||
{
|
||||
Host = string.IsNullOrEmpty(host) ? "localhost" : host;
|
||||
Port = port > 0 ? port : 8500;
|
||||
KeyOfServiceInConsul = keyOfServiceInConsul;
|
||||
Token = token;
|
||||
}
|
||||
|
||||
public string KeyOfServiceInConsul { get; }
|
||||
public string Host { get; }
|
||||
public int Port { get; }
|
||||
public string Token { get; }
|
||||
}
|
||||
}
|
@ -1,77 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
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 ConsulServiceDiscoveryProvider : IServiceDiscoveryProvider
|
||||
{
|
||||
private readonly ConsulRegistryConfiguration _config;
|
||||
private readonly IOcelotLogger _logger;
|
||||
private readonly IConsulClient _consul;
|
||||
private const string VersionPrefix = "version-";
|
||||
|
||||
public ConsulServiceDiscoveryProvider(ConsulRegistryConfiguration config, IOcelotLoggerFactory factory, IConsulClientFactory clientFactory)
|
||||
{;
|
||||
_logger = factory.CreateLogger<ConsulServiceDiscoveryProvider>();
|
||||
|
||||
_config = config;
|
||||
_consul = clientFactory.Get(_config);
|
||||
}
|
||||
|
||||
public async Task<List<Service>> Get()
|
||||
{
|
||||
var queryResult = await _consul.Health.Service(_config.KeyOfServiceInConsul, string.Empty, true);
|
||||
|
||||
var services = new List<Service>();
|
||||
|
||||
foreach (var serviceEntry in queryResult.Response)
|
||||
{
|
||||
if (IsValid(serviceEntry))
|
||||
{
|
||||
services.Add(BuildService(serviceEntry));
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.LogWarning($"Unable to use service Address: {serviceEntry.Service.Address} and Port: {serviceEntry.Service.Port} as it is invalid. Address must contain host only e.g. localhost and port must be greater than 0");
|
||||
}
|
||||
}
|
||||
|
||||
return services.ToList();
|
||||
}
|
||||
|
||||
private Service BuildService(ServiceEntry serviceEntry)
|
||||
{
|
||||
return new Service(
|
||||
serviceEntry.Service.Service,
|
||||
new ServiceHostAndPort(serviceEntry.Service.Address, serviceEntry.Service.Port),
|
||||
serviceEntry.Service.ID,
|
||||
GetVersionFromStrings(serviceEntry.Service.Tags),
|
||||
serviceEntry.Service.Tags ?? Enumerable.Empty<string>());
|
||||
}
|
||||
|
||||
private bool IsValid(ServiceEntry serviceEntry)
|
||||
{
|
||||
if (string.IsNullOrEmpty(serviceEntry.Service.Address) || serviceEntry.Service.Address.Contains("http://") || serviceEntry.Service.Address.Contains("https://") || serviceEntry.Service.Port <= 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private string GetVersionFromStrings(IEnumerable<string> strings)
|
||||
{
|
||||
return strings
|
||||
?.FirstOrDefault(x => x.StartsWith(VersionPrefix, StringComparison.Ordinal))
|
||||
.TrimStart(VersionPrefix);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,56 +0,0 @@
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
@ -1,26 +1,31 @@
|
||||
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.Logging;
|
||||
using Ocelot.ServiceDiscovery.Configuration;
|
||||
using Ocelot.ServiceDiscovery.Providers;
|
||||
using Ocelot.Values;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Steeltoe.Common.Discovery;
|
||||
|
||||
public class ServiceDiscoveryProviderFactory : IServiceDiscoveryProviderFactory
|
||||
{
|
||||
private readonly IOcelotLoggerFactory _factory;
|
||||
private readonly IConsulClientFactory _consulFactory;
|
||||
private readonly IDiscoveryClient _eurekaClient;
|
||||
private readonly List<ServiceDiscoveryFinderDelegate> _delegates;
|
||||
private readonly IServiceProvider _provider;
|
||||
|
||||
public ServiceDiscoveryProviderFactory(IOcelotLoggerFactory factory, IConsulClientFactory consulFactory, IDiscoveryClient eurekaClient)
|
||||
public ServiceDiscoveryProviderFactory(IOcelotLoggerFactory factory, IDiscoveryClient eurekaClient, IServiceProvider provider)
|
||||
{
|
||||
_factory = factory;
|
||||
_consulFactory = consulFactory;
|
||||
_eurekaClient = eurekaClient;
|
||||
_provider = provider;
|
||||
_delegates = provider
|
||||
.GetServices<ServiceDiscoveryFinderDelegate>()
|
||||
.ToList();
|
||||
}
|
||||
|
||||
public IServiceDiscoveryProvider Get(ServiceProviderConfiguration serviceConfig, DownstreamReRoute reRoute)
|
||||
@ -42,29 +47,27 @@ namespace Ocelot.ServiceDiscovery
|
||||
return new ConfigurationServiceProvider(services);
|
||||
}
|
||||
|
||||
private IServiceDiscoveryProvider GetServiceDiscoveryProvider(ServiceProviderConfiguration serviceConfig, string serviceName)
|
||||
private IServiceDiscoveryProvider GetServiceDiscoveryProvider(ServiceProviderConfiguration config, string key)
|
||||
{
|
||||
if (serviceConfig.Type?.ToLower() == "servicefabric")
|
||||
if (config.Type?.ToLower() == "servicefabric")
|
||||
{
|
||||
var config = new ServiceFabricConfiguration(serviceConfig.Host, serviceConfig.Port, serviceName);
|
||||
return new ServiceFabricServiceDiscoveryProvider(config);
|
||||
var sfConfig = new ServiceFabricConfiguration(config.Host, config.Port, key);
|
||||
return new ServiceFabricServiceDiscoveryProvider(sfConfig);
|
||||
}
|
||||
|
||||
if (serviceConfig.Type?.ToLower() == "eureka")
|
||||
if (config.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 new EurekaServiceDiscoveryProvider(key, _eurekaClient);
|
||||
}
|
||||
|
||||
return consulServiceDiscoveryProvider;
|
||||
// Todo - dont just hardcode this...only expect Consul at the momement so works.
|
||||
var finderDelegate = _delegates.FirstOrDefault();
|
||||
|
||||
var provider = finderDelegate?.Invoke(_provider, config, key);
|
||||
|
||||
return provider;
|
||||
}
|
||||
}
|
||||
|
||||
public delegate IServiceDiscoveryProvider ServiceDiscoveryFinderDelegate(IServiceProvider provider, ServiceProviderConfiguration config, string key);
|
||||
}
|
||||
|
Reference in New Issue
Block a user