🐛 Fixes on gateway multiple services case

This commit is contained in:
2025-07-15 20:43:44 +08:00
parent 3310487aba
commit 5549051ec5

View File

@ -12,7 +12,8 @@ public class RegistryProxyConfigProvider : IProxyConfigProvider, IDisposable
private readonly CancellationTokenSource _watchCts = new(); private readonly CancellationTokenSource _watchCts = new();
private CancellationTokenSource _cts = new(); private CancellationTokenSource _cts = new();
public RegistryProxyConfigProvider(IEtcdClient etcdClient, IConfiguration configuration, ILogger<RegistryProxyConfigProvider> logger) public RegistryProxyConfigProvider(IEtcdClient etcdClient, IConfiguration configuration,
ILogger<RegistryProxyConfigProvider> logger)
{ {
_etcdClient = etcdClient; _etcdClient = etcdClient;
_configuration = configuration; _configuration = configuration;
@ -48,7 +49,8 @@ public class RegistryProxyConfigProvider : IProxyConfigProvider, IDisposable
var pathAliases = _configuration.GetSection("PathAliases").GetChildren() var pathAliases = _configuration.GetSection("PathAliases").GetChildren()
.ToDictionary(x => x.Key, x => x.Value); .ToDictionary(x => x.Key, x => x.Value);
var directRoutes = _configuration.GetSection("DirectRoutes").Get<List<DirectRouteConfig>>() ?? new List<DirectRouteConfig>(); var directRoutes = _configuration.GetSection("DirectRoutes").Get<List<DirectRouteConfig>>() ??
[];
_logger.LogInformation("Indexing {ServiceCount} services from Etcd.", kvs.Count); _logger.LogInformation("Indexing {ServiceCount} services from Etcd.", kvs.Count);
@ -59,15 +61,19 @@ public class RegistryProxyConfigProvider : IProxyConfigProvider, IDisposable
{ {
if (serviceMap.TryGetValue(directRoute.Service, out var serviceUrl)) if (serviceMap.TryGetValue(directRoute.Service, out var serviceUrl))
{ {
var cluster = new ClusterConfig var existingCluster = clusters.FirstOrDefault(c => c.ClusterId == directRoute.Service);
if (existingCluster is null)
{ {
ClusterId = directRoute.Service, var cluster = new ClusterConfig
Destinations = new Dictionary<string, DestinationConfig>
{ {
{ "destination1", new DestinationConfig { Address = serviceUrl } } ClusterId = directRoute.Service,
} Destinations = new Dictionary<string, DestinationConfig>
}; {
clusters.Add(cluster); { "destination1", new DestinationConfig { Address = serviceUrl } }
}
};
clusters.Add(cluster);
}
var route = new RouteConfig var route = new RouteConfig
{ {
@ -76,7 +82,8 @@ public class RegistryProxyConfigProvider : IProxyConfigProvider, IDisposable
Match = new RouteMatch { Path = directRoute.Path } Match = new RouteMatch { Path = directRoute.Path }
}; };
routes.Add(route); routes.Add(route);
_logger.LogInformation(" Added Direct Route: {Path} -> {Service}", directRoute.Path, directRoute.Service); _logger.LogInformation(" Added Direct Route: {Path} -> {Service}", directRoute.Path,
directRoute.Service);
} }
else else
{ {
@ -95,27 +102,53 @@ public class RegistryProxyConfigProvider : IProxyConfigProvider, IDisposable
var serviceUrl = serviceMap[serviceName]; var serviceUrl = serviceMap[serviceName];
// Determine the path alias // Determine the path alias
string pathAlias; string? pathAlias;
if (pathAliases.TryGetValue(serviceName, out var alias)) pathAlias = pathAliases.TryGetValue(serviceName, out var alias)
? alias
: serviceName.Split('.').Last().ToLowerInvariant();
_logger.LogInformation(" Service: {ServiceName}, URL: {ServiceUrl}, Path Alias: {PathAlias}", serviceName,
serviceUrl, pathAlias);
// Check if the cluster already exists
var existingCluster = clusters.FirstOrDefault(c => c.ClusterId == serviceName);
if (existingCluster == null)
{ {
pathAlias = alias; var cluster = new ClusterConfig
{
ClusterId = serviceName,
Destinations = new Dictionary<string, DestinationConfig>
{
{ "destination1", new DestinationConfig { Address = serviceUrl } }
}
};
clusters.Add(cluster);
_logger.LogInformation(" Added Cluster: {ServiceName}", serviceName);
} }
else else
{ {
pathAlias = serviceName.Split('.').Last().ToLowerInvariant(); // Create a new cluster with merged destinations
} var newDestinations = new Dictionary<string, DestinationConfig>(existingCluster.Destinations)
_logger.LogInformation(" Service: {ServiceName}, URL: {ServiceUrl}, Path Alias: {PathAlias}", serviceName, serviceUrl, pathAlias);
var cluster = new ClusterConfig
{
ClusterId = serviceName,
Destinations = new Dictionary<string, DestinationConfig>
{ {
{ "destination1", new DestinationConfig { Address = serviceUrl } } {
} $"destination{existingCluster.Destinations.Count + 1}",
}; new DestinationConfig { Address = serviceUrl }
clusters.Add(cluster); }
};
var mergedCluster = new ClusterConfig
{
ClusterId = serviceName,
Destinations = newDestinations
};
// Replace the existing cluster with the merged one
var index = clusters.IndexOf(existingCluster);
clusters[index] = mergedCluster;
_logger.LogInformation(" Updated Cluster {ServiceName} with {DestinationCount} destinations",
serviceName, mergedCluster.Destinations.Count);
}
// Host-based routing // Host-based routing
if (domainMappings.TryGetValue(serviceName, out var domain)) if (domainMappings.TryGetValue(serviceName, out var domain))
@ -126,7 +159,7 @@ public class RegistryProxyConfigProvider : IProxyConfigProvider, IDisposable
ClusterId = serviceName, ClusterId = serviceName,
Match = new RouteMatch Match = new RouteMatch
{ {
Hosts = new[] { domain }, Hosts = [domain],
Path = "/{**catch-all}" Path = "/{**catch-all}"
} }
}; };
@ -142,7 +175,8 @@ public class RegistryProxyConfigProvider : IProxyConfigProvider, IDisposable
Match = new RouteMatch { Path = $"/{pathAlias}/{{**catch-all}}" }, Match = new RouteMatch { Path = $"/{pathAlias}/{{**catch-all}}" },
Transforms = new List<Dictionary<string, string>> Transforms = new List<Dictionary<string, string>>
{ {
new Dictionary<string, string> { { "PathRemovePrefix", $"/{pathAlias}" } } new() { { "PathRemovePrefix", $"/{pathAlias}" } },
new() { { "PathPrefix", "/api" } }
} }
}; };
routes.Add(pathRoute); routes.Add(pathRoute);
@ -157,16 +191,18 @@ public class RegistryProxyConfigProvider : IProxyConfigProvider, IDisposable
{ {
public IReadOnlyList<RouteConfig> Routes { get; } = routes; public IReadOnlyList<RouteConfig> Routes { get; } = routes;
public IReadOnlyList<ClusterConfig> Clusters { get; } = clusters; public IReadOnlyList<ClusterConfig> Clusters { get; } = clusters;
public Microsoft.Extensions.Primitives.IChangeToken ChangeToken { get; } = new Microsoft.Extensions.Primitives.CancellationChangeToken(CancellationToken.None);
public Microsoft.Extensions.Primitives.IChangeToken ChangeToken { get; } =
new Microsoft.Extensions.Primitives.CancellationChangeToken(CancellationToken.None);
} }
private class DirectRouteConfig private record DirectRouteConfig
{ {
public string Path { get; set; } public required string Path { get; set; }
public string Service { get; set; } public required string Service { get; set; }
} }
public void Dispose() public virtual void Dispose()
{ {
_cts.Cancel(); _cts.Cancel();
_cts.Dispose(); _cts.Dispose();