问题描述
我有一个关于微服务架构设计的多租户应用程序。
我想注入 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)