-
Notifications
You must be signed in to change notification settings - Fork 1.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Connection errors when Consul node names are not real DNS hosts #954
Comments
My framework is. NetCore 2.2 |
楼主,这个问题你解决了吗? |
还没有解决,目前恢复到了13.5.0版本在使用。一直没有时间去解决这个问题,项目比较紧急。 |
这是7月一次#909,支持SSL认证加入的处理。如果有node,下游地址使用node.name。但是dns肯定不认识的。我也反映了下,不知道这边应该怎么做,consul本身是有dns服务器的 |
这个问题你解决了吗? |
降版本了 |
这个问题我尝试着解决了一下,我也不会英语. 经过以上的处理,就解决了这个问题,希望能到你们帮助. |
补充一下,如果大家使用的是docker容器,一般就不会有这种情况发生. |
改主机名是没问题的,这跟ocelot无关,只是dns根据hostname能够解析出主机ip |
但是我感觉改主机名还是不对的,不应该这样,ocelot既然能访问,还是应该按照以前的ip方式去访问才对. |
不知道为什么13.5.1以后的版本会这样处理,不知道为什么 |
看pr是为了解决ssl问题,看作者最后怎么支持了。目前强制使用node name的方式肯定是不支持有些场景。原则上consul支持dns服务,可以从这个角度入手。但是也不应该是node name而是按照consul的服务名+后缀的方式。如果consul的node接口不返回信息,也是使用ip的方式 |
对的,看后续作者如何处理了.我就先这么用着了. |
We can’t understand to help you guys. |
ocelot with consul dynamic reroute use node name instead of service host ip after pr (#909). but the node name is not always host name. so our code get error of host error of dns. |
现在的版本还有这个问题,大家怎么解决的啊? 我修改hosts文件没成功.所以就投机把node设置成127.0.0.1,可以运行. |
Could you upgrade to the latest v22.0.1 please?
🆗 What's your vision of fixing it? Do you have a plan to fix? |
It seems the author has deleted his(er) GitHub account... Cannot communicate... @ggnaegi Could you consult us here plz? |
@raman-m it's very old... |
"2 days ago", great! :D I've encountered this bug back in 2022 and again, just 3 days ago, still need to migrate one service and it will help a lot. My issue is that before, Ocelot used configured IP address to call the service, now it uses consul node name? or machine name? and it breaks work on local stations. I can probably somehow configure it on server but locally I really liked the way of resolving addresses from version 13.0.0 (before this commit I guess: b707cd6)
Maybe some backwards compability? |
@ignacy130 Are you the author (@ghost)? 😺 Will you personally contribute to help us to fix this design issue? |
@ignacy130 I agree, it is significant problem for different Consul configurations and Consul setup scenarios. Could you fork Ocelot repo into your account please? This link should work... Ocelot/src/Ocelot.Provider.Consul/Consul.cs Lines 54 to 65 in f4803c2
And let me know your ideas how we could refactor the class plz |
@ignacy130 And I've just realized that your problem can be solved by Custom Providers... |
I don't use dynamic routing, just classic setting. Once I've started debugging I thought about overriding this Consul.cs somehow and Custom Providers seem like a good solution - I'll have a look at this! |
@ignacy130 Good luck in development! |
Got it working, thank you! The more complicated way of configuring custom provider worked better for me. Name of the class is stupid maybe but works for now XD ocelot.json: "GlobalConfiguration": {
"ServiceDiscoveryProvider": {
"Type": "ConsulProviderResolvingAddressNotConsulNodeName"
}
} Startup.cs: services.RemoveAll<IServiceDiscoveryProviderFactory>();
services.AddSingleton<IServiceDiscoveryProviderFactory, CustomConsulProviderFactory>();
services.AddSingleton<ServiceDiscoveryFinderDelegate>((serviceProvider, config, downstreamRoute) => null);
services.AddSingleton<IConsulClientFactory>(new ConsulClientFactory());
services.AddOcelot(_cfg).AddConfigStoredInConsul(); //Note: no .AddConsul() call! The rest i basically a copy-paste from old way (13.0.0) of resolving services via Consul and provider factory: public class ConsulProviderResolvingAddressNotConsulNodeName : IServiceDiscoveryProvider
{
private const string VersionPrefix = "version-";
private readonly ConsulRegistryConfiguration _config;
private readonly IConsulClient _consul;
private readonly IOcelotLogger _logger;
public ConsulProviderResolvingAddressNotConsulNodeName(ConsulRegistryConfiguration config, IOcelotLoggerFactory factory, IConsulClientFactory clientFactory)
{
_config = config;
_consul = clientFactory.Get(_config);
_logger = factory.CreateLogger<ConsulProviderResolvingAddressNotConsulNodeName>();
}
public async Task<List<Service>> GetAsync()
{
var queryResult = await _consul.Health.Service(_config.KeyOfServiceInConsul, string.Empty, false);
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);
}
}
public class CustomConsulProviderFactory : IServiceDiscoveryProviderFactory
{
/// <summary>
/// String constant used for provider type definition.
/// </summary>
public const string PollConsul = nameof(ConsulProviderResolvingAddressNotConsulNodeName);
private static readonly List<PollConsul> ServiceDiscoveryProviders = new();
private static readonly object LockObject = new();
private IOcelotLoggerFactory _factory;
private IServiceProvider _provider;
public CustomConsulProviderFactory(IOcelotLoggerFactory factory, IServiceProvider provider)
{
_factory = factory;
_provider = provider;
}
private IServiceDiscoveryProvider CreateProvider(
ServiceProviderConfiguration config, DownstreamRoute route)
{
var factory = _provider.GetService<IOcelotLoggerFactory>();
var consulFactory = _provider.GetService<IConsulClientFactory>();
var consulRegistryConfiguration = new ConsulRegistryConfiguration(
config.Scheme, config.Host, config.Port, route.ServiceName, config.Token);
var consulProvider = new ConsulProviderResolvingAddressNotConsulNodeName(consulRegistryConfiguration, factory, consulFactory);
if (PollConsul.Equals(config.Type, StringComparison.OrdinalIgnoreCase))
{
lock (LockObject)
{
var discoveryProvider = ServiceDiscoveryProviders.FirstOrDefault(x => x.ServiceName == route.ServiceName);
if (discoveryProvider != null)
{
return discoveryProvider;
}
discoveryProvider = new PollConsul(config.PollingInterval, route.ServiceName, factory, consulProvider);
ServiceDiscoveryProviders.Add(discoveryProvider);
return discoveryProvider;
}
}
return consulProvider;
}
Response<IServiceDiscoveryProvider> IServiceDiscoveryProviderFactory.Get(ServiceProviderConfiguration serviceConfig, DownstreamRoute route)
{
return new OkResponse<IServiceDiscoveryProvider>(CreateProvider(serviceConfig, route));
}
} |
@ignacy130 Hi Ignacy! @ggnaegi FYI |
…e discovery provider (#2067) * Interfaces folder and namespace * `IConsulServiceBuilder` interface vs `ConsulServiceBuilder` class * Inject services into `ConsulServiceBuilder` * Extend `IConsulServiceBuilder` interface * Finalize design of the customization. No JSON options because `ServiceDiscoveryProvider` are generalized for all types of providers * Remove BDDfy in favor of AAA pattern * Refactor original unit tests * Rename to `DefaultConsulServiceBuilder` * Update src/Ocelot.Provider.Consul/DefaultConsulServiceBuilder.cs Update `IsValid(ServiceEntry entry)` Co-authored-by: Raynald Messié <[email protected]> * Code review by @RaynaldM * Read the node instance from `ServiceEntry`. If it is null, search for a node in the common collection. * Refactor `OcelotBuilderExtensionsTests` * The generic `AddConsul<TServiceBuilder>(IOcelotBuilder)` method * Rename to `ConsulTests` * Unit tests: 100% coverage * Move to `ServiceDiscovery` folder * DRY: GivenServiceEntry, GivenRoute * Convert to file-scoped namespace * Inherit from `Steps` * Refactor acceptance tests * Acceptance test for #954 user scenario * Move "Store Configuration in Consul" to "Service Discovery" * Feature docs --------- Co-authored-by: Raynald Messié <[email protected]>
@ignacy130 you saved my day |
@ignacy130 @Jayfend |
Expected Behavior / New Feature
Ocelot.Provider.Consul version 13.5.2
Actual Behavior / Motivation for New Feature
I used
Ocelot.Provider.Consul
and Consul, but when I make an API request,the console display error
But when I use
Ocelot.Provider.Consul
version 13.5.0 there is no problemSteps to Reproduce the Problem
consul server configuration:
Specifications
The text was updated successfully, but these errors were encountered: