Azure Service Fabric 多租户

6

我想对已经回答的这个问题进行一些跟进...

Service Fabric 多租户

如果我将我的租户设置为 Azure Service Fabric 无状态服务(它们会在带外获取其状态),如何在集群中的每个节点上放置多个租户?在测试中,如果您尝试使实例计数大于节点计数,则 Service Fabric 会报错。

这些租户非常轻量级,因此我应该能够在每个节点上运行数十个(总计数将达到数百个),我不想为每个租户都做一个节点。具体来说,这些租户或多或少只是向外部客户服务打开了一个长轮询 HTTP 连接,并将数据流回我们的系统-因此这里没有公共终结点。我只需要能够启动许多这些将各自打开自己的长轮询连接的工作程序的能力。

有人可以给我指点方向吗?

提醒一下,我在这里解释了更多细节... https://social.msdn.microsoft.com/Forums/en-US/efd172e2-0783-489b-b3ab-ec62fb7b8ee4/multiple-instances-per-node?forum=AzureServiceFabric

先行感谢!

1个回答

8

您需要对服务进行分区。

有几个选项,但是两个与此处(以及您链接的SO问题)相符的选项是:

创建一个SF应用程序,在其中每个租户都获得您服务的一个实例。然后,您需要在前面拥有一个共享服务,以将请求路由到正确的服务。它应该看起来像这样。

MyAwesomeApp
    SharedStatelessApi <- External API points here
    MyTenantService_Tenant1 <- ServiceType: MyTenantService
    MyTenantService_Tenant2 <- ServiceType: MyTenantService
    ...

另一个解决方案是为每个租户创建一个(或多个)服务织物应用程序,可能会如下所示:
MySharedApp
    SharedStatelessApi <- External API points here
Tenant1 <- ApplicationType: MyTenantApp
    MyTenantService <- ServiceType: MyTenantService
Tenant2 <- ApplicationType: MyTenantApp
    MyTenantService <- ServiceType: MyTenantService

这是与第一个例子相同的概念,但分区是在更高层次上完成的。

个人而言,我更喜欢第二种情况。它感觉更正确。 在两种情况下,您都必须在新客户注册时手动创建服务/应用程序,或者在代码中执行此操作。如果要在代码中执行此操作,应查看FabricClient。如果需要示例,请告诉我。

另外,正如您所见,您应该拥有共享的公共端点,并在该端点中基于某些内容(标题、身份验证令牌、URI等)将请求路由到正确的服务。

使用FabricClient创建服务的示例:

首先,您需要一个FabricClient。对于未经保护的群集(本地开发群集),以下内容就足够了:

var fabricClient = new FabricClient("localhost:19000");

当您部署到安全集群(例如在Azure中)时,您需要对FabricClient进行身份验证,如下所示:

var creds = new X509Credentials
{
    FindType = X509FindType.FindByThumbprint,
    FindValue = clientCertThumbprint,
    RemoteCertThumbprints = {clientCertThumbprint},
    StoreLocation = StoreLocation.LocalMachine,
    StoreName = "My"
};

var clusterEndpoint = "CLUSTERNAME.LOCATION.cloudapp.azure.com:19000"
// or whatever your cluster endpoint is

var fabricClient = new FabricClient(creds, clusterEndpoint);

然后,当你拥有一个FabricClient时,可以像这样创建一个无状态服务:

var statelessDescriptor = new StatelessServiceDescription
{
    ApplicationName = new Uri("fabric:/MYAPP"),
    InstanceCount = 1, // How many instances.
    PartitionSchemeDescription = new SingletonPartitionSchemeDescription(),
    ServiceName = new Uri("fabric:/MYAPP/TenantA"),
    ServiceTypeName = "YourServiceTypeName",
    InitializationData = DATA_TO_PASS_TO_SERVICE_BYTE[] // Only if needed.
};

await _client.ServiceManager.CreateServiceAsync(statelessDescriptor)

如果您在“InitializationData”属性中传递了任何数据,则可以在服务中将其作为ServiceInitializationParameters.InitializationData使用。

感谢您抽出时间提供反馈。也许我需要更多地研究FabricClient和您提出的解决方案,以确定它是否是我正在寻找的答案的一部分。请记住,我们的多租户服务实际上只是打开长轮询HTTP连接并从客户端流式传输数据的过程 - 没有公共端点。问题在于,我们需要在每个节点上运行几个租户的实例,因为它们非常轻量级,使用一个节点完全浪费了该节点的性能。 - cwiederspan
好的,假设您有某种内部方式来触发连接的初始化,那么我上面的帖子仍然适用。例如,您可以不触发与租户A的连接,而是为租户A启动一个无状态服务实例,并且该服务在其RunAsync方法中打开其连接。这有意义吗? - anderso
或许我可以尝试更好地理解您的需求。您希望每个长时间运行的连接有一个状态服务实例吗?连接/租户的数量是固定的,还是随着时间的推移会增加/减少? - anderso
是的,想法是为每个“客户”都有一个服务,但是当服务“初始化”时,它将会打开该长期运行的连接,并在该开放的连接上不断地流式传输数据。客户将以一两个的方式出现和离开,但我可以想象总是有额外的实例被激活,每小时击中配置服务器以查看是否有需要开始流式传输的新客户,这将是初始化过程。同样,在关闭连接时,如果客户取消,我们将只将该实例添加回可用工作程序的堆中。 - cwiederspan
好的,我明白了。那么我会按照上面所说的,在需要时在代码中为每个客户创建一个租户服务实例。然后,您可以在InitializationData字段中传递所需的数据,以便实例知道要连接到谁。当客户离开时也是同样的操作,只需删除该实例即可。除非时间非常关键,否则根据我们的经验,没有必要拥有备用实例,因为创建无状态服务只需要几秒钟。 - anderso
显示剩余8条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接