♻️ Update service discovery code

This commit is contained in:
2025-12-13 18:52:55 +08:00
parent 42082fbefa
commit 3a7140f0a6
14 changed files with 70 additions and 62 deletions

View File

@@ -9,8 +9,6 @@ public static class DysonAuthStartup
this IServiceCollection services
)
{
services.AddAuthService();
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = AuthConstants.SchemeName;

View File

@@ -7,6 +7,7 @@ using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Diagnostics.HealthChecks;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.ServiceDiscovery;
using NodaTime;
using OpenTelemetry;
using OpenTelemetry.Metrics;
@@ -52,11 +53,20 @@ public static class Extensions
// options.AllowedSchemes = ["https"];
// });
var etcdClient = new EtcdClient(builder.Configuration.GetConnectionString("Registrar"));
var registrar = new ServiceRegistrar(etcdClient);
builder.Services.AddSingleton<IClock>(SystemClock.Instance);
builder.Services.AddSingleton(new EtcdClient(builder.Configuration.GetConnectionString("Registrar")));
builder.Services.AddSingleton<ServiceRegistrar>();
builder.Services.AddSingleton(etcdClient);
builder.Services.AddSingleton(registrar);
builder.Services.AddHostedService<ServiceRegistrarHostedService>();
builder.Services.AddRingService(registrar);
builder.Services.AddAuthService(registrar);
builder.Services.AddAccountService(registrar);
builder.Services.AddSphereService(registrar);
builder.Services.AddDriveService(registrar);
builder.Services.AddDevelopService(registrar);
builder.AddNatsClient("Queue");
builder.AddRedisClient("Cache", configureOptions: opts => { opts.AbortOnConnectFail = false; });

View File

@@ -1,14 +1,17 @@
using DysonNetwork.Shared.Proto;
using Grpc.Net.ClientFactory;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
namespace DysonNetwork.Shared.Registry;
public static class ServiceInjectionHelper
{
public static IServiceCollection AddRingService(this IServiceCollection services)
public static IServiceCollection AddRingService(this IServiceCollection services, ServiceRegistrar registrar)
{
var instance = registrar.GetServiceInstanceAsync("ring", "grpc").GetAwaiter().GetResult();
services
.AddGrpcClient<RingService.RingServiceClient>(o => o.Address = new Uri("https://_grpc.ring"))
.AddGrpcClient<RingService.RingServiceClient>(o => o.Address = new Uri(instance))
.ConfigurePrimaryHttpMessageHandler(_ => new HttpClientHandler()
{ ServerCertificateCustomValidationCallback = (_, _, _, _) => true }
);
@@ -16,16 +19,17 @@ public static class ServiceInjectionHelper
return services;
}
public static IServiceCollection AddAuthService(this IServiceCollection services)
public static IServiceCollection AddAuthService(this IServiceCollection services, ServiceRegistrar registrar)
{
var instance = registrar.GetServiceInstanceAsync("pass", "grpc").GetAwaiter().GetResult();
services
.AddGrpcClient<AuthService.AuthServiceClient>(o => o.Address = new Uri("https://_grpc.pass"))
.AddGrpcClient<AuthService.AuthServiceClient>(o => o.Address = new Uri(instance))
.ConfigurePrimaryHttpMessageHandler(_ => new HttpClientHandler()
{ ServerCertificateCustomValidationCallback = (_, _, _, _) => true }
);
services
.AddGrpcClient<PermissionService.PermissionServiceClient>(o => o.Address = new Uri("https://_grpc.pass"))
.AddGrpcClient<PermissionService.PermissionServiceClient>(o => o.Address = new Uri(instance))
.ConfigurePrimaryHttpMessageHandler(_ => new HttpClientHandler()
{ ServerCertificateCustomValidationCallback = (_, _, _, _) => true }
);
@@ -33,10 +37,11 @@ public static class ServiceInjectionHelper
return services;
}
public static IServiceCollection AddAccountService(this IServiceCollection services)
public static IServiceCollection AddAccountService(this IServiceCollection services, ServiceRegistrar registrar)
{
var instance = registrar.GetServiceInstanceAsync("pass", "grpc").GetAwaiter().GetResult();
services
.AddGrpcClient<AccountService.AccountServiceClient>(o => o.Address = new Uri("https://_grpc.pass"))
.AddGrpcClient<AccountService.AccountServiceClient>(o => o.Address = new Uri(instance))
.ConfigurePrimaryHttpMessageHandler(_ => new HttpClientHandler()
{ ServerCertificateCustomValidationCallback = (_, _, _, _) => true }
);
@@ -44,42 +49,42 @@ public static class ServiceInjectionHelper
services
.AddGrpcClient<BotAccountReceiverService.BotAccountReceiverServiceClient>(o =>
o.Address = new Uri("https://_grpc.pass")
o.Address = new Uri(instance)
)
.ConfigurePrimaryHttpMessageHandler(_ => new HttpClientHandler()
{ ServerCertificateCustomValidationCallback = (_, _, _, _) => true }
);
services.AddGrpcClient<ActionLogService.ActionLogServiceClient>(o => o.Address = new Uri("https://_grpc.pass"))
services.AddGrpcClient<ActionLogService.ActionLogServiceClient>(o => o.Address = new Uri(instance))
.ConfigurePrimaryHttpMessageHandler(_ => new HttpClientHandler()
{ ServerCertificateCustomValidationCallback = (_, _, _, _) => true }
);
services.AddGrpcClient<PaymentService.PaymentServiceClient>(o => o.Address = new Uri("https://_grpc.pass"))
services.AddGrpcClient<PaymentService.PaymentServiceClient>(o => o.Address = new Uri(instance))
.ConfigurePrimaryHttpMessageHandler(_ => new HttpClientHandler()
{ ServerCertificateCustomValidationCallback = (_, _, _, _) => true }
);
services.AddGrpcClient<WalletService.WalletServiceClient>(o => o.Address = new Uri("https://_grpc.pass"))
services.AddGrpcClient<WalletService.WalletServiceClient>(o => o.Address = new Uri(instance))
.ConfigurePrimaryHttpMessageHandler(_ => new HttpClientHandler()
{ ServerCertificateCustomValidationCallback = (_, _, _, _) => true }
);
services
.AddGrpcClient<RealmService.RealmServiceClient>(o => o.Address = new Uri("https://_grpc.pass"))
.AddGrpcClient<RealmService.RealmServiceClient>(o => o.Address = new Uri(instance))
.ConfigurePrimaryHttpMessageHandler(_ => new HttpClientHandler()
{ ServerCertificateCustomValidationCallback = (_, _, _, _) => true }
);
services.AddSingleton<RemoteRealmService>();
services
.AddGrpcClient<SocialCreditService.SocialCreditServiceClient>(o => o.Address = new Uri("https://_grpc.pass"))
.AddGrpcClient<SocialCreditService.SocialCreditServiceClient>(o => o.Address = new Uri(instance))
.ConfigurePrimaryHttpMessageHandler(_ => new HttpClientHandler()
{ ServerCertificateCustomValidationCallback = (_, _, _, _) => true }
);
services
.AddGrpcClient<ExperienceService.ExperienceServiceClient>(o => o.Address = new Uri("https://_grpc.pass"))
.AddGrpcClient<ExperienceService.ExperienceServiceClient>(o => o.Address = new Uri(instance))
.ConfigurePrimaryHttpMessageHandler(_ => new HttpClientHandler()
{ ServerCertificateCustomValidationCallback = (_, _, _, _) => true }
);
@@ -87,9 +92,10 @@ public static class ServiceInjectionHelper
return services;
}
public static IServiceCollection AddDriveService(this IServiceCollection services)
public static IServiceCollection AddDriveService(this IServiceCollection services, ServiceRegistrar registrar)
{
services.AddGrpcClient<FileService.FileServiceClient>(o => o.Address = new Uri("https://_grpc.drive"))
var instance = registrar.GetServiceInstanceAsync("drive", "grpc").GetAwaiter().GetResult();
services.AddGrpcClient<FileService.FileServiceClient>(o => o.Address = new Uri(instance))
.ConfigurePrimaryHttpMessageHandler(_ => new HttpClientHandler()
{ ServerCertificateCustomValidationCallback = (_, _, _, _) => true }
);
@@ -103,32 +109,33 @@ public static class ServiceInjectionHelper
return services;
}
public static IServiceCollection AddSphereService(this IServiceCollection services)
public static IServiceCollection AddSphereService(this IServiceCollection services, ServiceRegistrar registrar)
{
var instance = registrar.GetServiceInstanceAsync("drive", "grpc").GetAwaiter().GetResult();
services
.AddGrpcClient<PostService.PostServiceClient>(o => o.Address = new Uri("https://_grpc.sphere"))
.AddGrpcClient<PostService.PostServiceClient>(o => o.Address = new Uri(instance))
.ConfigurePrimaryHttpMessageHandler(_ => new HttpClientHandler()
{ ServerCertificateCustomValidationCallback = (_, _, _, _) => true }
);
services
.AddGrpcClient<PublisherService.PublisherServiceClient>(o => o.Address = new Uri("https://_grpc.sphere"))
.AddGrpcClient<PublisherService.PublisherServiceClient>(o => o.Address = new Uri(instance))
.ConfigurePrimaryHttpMessageHandler(_ => new HttpClientHandler()
{ ServerCertificateCustomValidationCallback = (_, _, _, _) => true }
);
services.AddSingleton<RemotePublisherService>();
return services;
}
public static IServiceCollection AddDevelopService(this IServiceCollection services)
public static IServiceCollection AddDevelopService(this IServiceCollection services, ServiceRegistrar registrar)
{
var instance = registrar.GetServiceInstanceAsync("develop", "grpc").GetAwaiter().GetResult();
services.AddGrpcClient<CustomAppService.CustomAppServiceClient>(o =>
o.Address = new Uri("https://_grpc.develop"))
o.Address = new Uri(instance))
.ConfigurePrimaryHttpMessageHandler(_ => new HttpClientHandler()
{ ServerCertificateCustomValidationCallback = (_, _, _, _) => true }
);
return services;
}
}
}

View File

@@ -85,14 +85,15 @@ public class ServiceRegistrar(EtcdClient etcd)
public async Task<List<string>> GetServiceInstancesAsync(string serviceName, string servicePart)
{
var prefix = $"/services/{serviceName}/{servicePart}/";
var request = new RangeRequest
while (true)
{
Key = ByteString.CopyFromUtf8(prefix),
RangeEnd = ByteString.CopyFromUtf8(prefix + "\0")
};
var response = await etcd.GetAsync(request);
var instances = response.Kvs.Select(kv => kv.Value.ToStringUtf8()).ToList();
return instances;
var response = await etcd.GetRangeAsync(prefix);
var instances = response.Kvs.Select(kv => kv.Value.ToStringUtf8()).ToList();
if (instances.Count > 0)
return instances;
Console.WriteLine($"No instances found for service '{serviceName}/{servicePart}', retrying...");
await Task.Delay(1000);
}
}
/// <summary>
@@ -104,8 +105,7 @@ public class ServiceRegistrar(EtcdClient etcd)
if (instances.Count == 0)
throw new InvalidOperationException($"No instances found for service '{serviceName}' part '{servicePart}'");
var key = $"{serviceName}/{servicePart}";
if (!_roundRobinCounters.ContainsKey(key))
_roundRobinCounters[key] = 0;
_roundRobinCounters.TryAdd(key, 0);
var instance = instances[_roundRobinCounters[key] % instances.Count];
_roundRobinCounters[key] = (_roundRobinCounters[key] + 1) % int.MaxValue;
return instance;