无论如何在运行时向服务提供者添加服务?还是重建?在 .NET 5.0 或 .NET core 3+ 上

问题描述

我有一个关于微服务架构设计的多租户应用程序。

我想注入 X 个服务,具体取决于运行的租户数量。

 public void ConfigureServices(IServiceCollection services)
    {
        // ... OTHER DI

        services.AddHttpClient("TenantsService")
            .AddTypedClient<ITenantServiceClient>(c => new TenantServiceClient(new TenantServiceClientSettings()
            {
                AccessKey = Configuration["TenantsService:ApiKey"],BaseUrl = new Uri(Configuration["TenantsService:Url"])
            },c)); 

        foreach (var tenant in TenantsToRegister)
        {
            services
                .AddGraphQLServer($"{tenant.Name}");
        }

        ...

    }

如果我在应用程序启动时有租户列表,上面的代码就可以工作。但我需要从另一个微服务请求该列表。有了这个限制,我需要构建服务提供者才能获得该列表。同时,我需要服务提供者构建之前的列表来注入我需要的服务。

我看到的唯一选择是在运行时添加服务,但我不确定是否可行。

解决方法

您遇到了问题...您正在尝试在多租户环境中垂直扩展。你会用10个租户做什么? 100?单个节点上的单个进程需要大量 ram(如果您 100% 确定您将拥有其中一些,则可能不是这种情况)而没有任何机会水平扩展

我认为您可以从相同的图像为每个租户创建服务,但不同的配置和 api 网关/负载均衡器取决于...东西...(标题、查询参数、用户 ID 等)。它可能需要一些基础设施投资,但未来不会很痛苦

如果您真的想从 http 客户端加载租户信息,然后为每个租户添加 HC gql 服务器,我建议您编写自己的 IConfiguration 提供程序。

这是 Consul 集成,它具有与您需要的相同的 http 往返 https://github.com/wintoncode/Winton.Extensions.Configuration.Consul。它添加自定义配置源并在启动时加载它

之后,您只需在启动时从配置映射租户信息

,

从架构的角度来看,我建议为每个租户使用“真正的”服务。例如,为每个租户启动 docker 或应用程序进程。就像在以前的答案中写的一样(感谢 sergey)。

如果您真的想在同一进程中为每个租户启动一个新的 GraphQLServer,那么我会这样做: Full example on dotnet fiddle

services
    .AddHttpClient("TenantsService")
    .AddTypedClient<ITenantServiceClient>(c => 
                                    new TenantServiceClient(new TenantServiceClientSettings
                                    {
                                        AccessKey = "THE KEY",// Configuration["TenantsService:ApiKey"],BaseUrl = new Uri("https://the-uri-you-need.com") // new Uri(Configuration["TenantsService:Url"])
                                    },c));
        
// build a temporary service provider before,with all services added until now.
var tempServiceProvider = services.BuildServiceProvider();

// resolve the tenant service and query for tenants
var tenantsToRegister = tempServiceProvider.GetRequiredService<ITenantServiceClient>().GetTenants();

// register needed tenants
foreach (var tenant in tenantsToRegister)
{
    services.AddGraphQLServer($"{tenant}");
}

...当然,必须添加围绕对 ITenantServiceClient 调用的整个错误处理,但这仅用于演示目的。 这里的特殊之处在于中间 IServiceProvider,它使您能够使用完整的 DI 集来查询您的租户,但之后您可以添加所需的。

但是:这也是在启动时,不能在运行时添加额外的服务器。

更新 这是 updated dotnet fiddle(感谢 joao-figueira)

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...