如何到达无状态服务的特定副本

How can I reach a specific replica of a stateless service

我在 Service Fabric 中创建了一个无状态服务。它有一个 SingletonPartition,但有多个实例(在我的例子中 InstanceCount 是 -1)。

我想与此服务的特定副本进行通信。要查找我使用的所有副本:

var fabricClient = new FabricClient();
var serviceUri = new Uri(SERVICENAME);

Partition partition = (await fabricClient.QueryManager.GetPartitionListAsync(serviceUri)).First();
foreach(Replica replica in await fabricClient.QueryManager.GetReplicaListAsync(partition.PartitionInformation.Id))
{
  // communicate with this replica, but how to construct the proxy?
  //var eventHandlerServiceClient = ServiceProxy.Create<IService>(new Uri(replica.ReplicaAddress));
}

问题是没有重载 ServiceProxy 来为副本创建一个。是否有其他方式与特定副本通信?

编辑

我们正在构建的场景如下。我们有不同的带有计数器信息的移动部件:1 个命名的分区有状态服务(有几百个分区),1 个 int64 分区有状态服务,和 1 个有状态的参与者。要聚合计数器信息,我们需要接触所有服务分区和参与者实例。

我们当然可以反转它,让每个人都将计数发送到单个(分区)服务。但这会在正常流程中添加网络调用(因此会增加开销)。

相反,我们想到了以下内容。上述服务和参与者合并为一个可执行文件和一个服务清单。因此他们在同一个进程中。我们将 instancecount -1 的无状态服务添加到提到的服务和参与者中。所有计数器信息都存储在一个静态变量中。无状态服务可以读取此计数器信息。 现在,我们只需要接触到无状态服务(有节点数上限)。

先排除一些术语,"replica" 仅适用于有状态服务,其中您为服务的每个分区设置唯一的副本集,并在它们之间复制状态以实现 HA。无状态服务只有实例,所有实例都是相同的。

现在回答您的实际问题:ServiceProxy 没有连接到已部署无状态服务的特定实例的选项。您有以下选择:

  • 主副本:连接到有状态服务分区的主副本。
  • 随机实例:连接到无状态服务的随机实例。
  • 随机副本:连接到有状态服务分区的随机副本 - 无论其角色如何。
  • 随机辅助副本 - 连接到有状态服务分区的随机辅助副本。

例如:

ServiceProxy.Create<IMyService>(serviceUri, partitionKey, TargetReplicaSelector.RandomInstance)

那么为什么没有连接到特定无状态服务实例的选项?

好吧,我会反过来问你为什么 想要 连接到特定的无状态服务实例?根据定义,每个无状态实例都应该是相同的。如果您在那里保留一些状态 - 例如用户会话 - 那么现在您是有状态的并且应该使用有状态服务。

您可能会考虑智能地决定连接到哪个实例以实现负载平衡,但由于它是无状态的,因此只要请求均匀分布,任何实例都不应比其他实例做更多的工作。为此,Service Proxy 具有随机分发选项。

考虑到这一点,如果您仍然有理由寻找特定的无状态服务实例,您始终可以使用不同的通信堆栈(如 HTTP)并做任何您想做的事情。

"Well, I would turn this question around and ask why would you want to connect to a specific stateless service instance?"

一个示例是,如果您有多个 (3x) 无状态服务实例,它们都具有到不同客户端的 WebSocket 连接,假设每个实例有 500 个。如果可以直接连接到特定实例(我希望这是可能的,因为我可以使用 FabricClient 查询这些实例),并且您想要通知所有 1500 (500x3) 用户相同的消息,我可以发送给每个实例的消息,将其重定向到所有连接的客户端。

相反,我们必须想出多种解决方法中的任何一种:

  1. 让所有实例都连接到某个允许它们触发传入消息的事件系统,例如Azure 事件中心、Azure 服务总线、RedisCache。

  2. 托管一个附加端点,如此处所述,这使它成为 3 个端点 pr 服务实例:WCF、WebSocket、HTTP。

  3. 更改为不保存任何状态或任何副本的有状态分区服务,但只允许调用分区。

目前 RedisCache 存在一些严重的问题,因此要远离它,并且希望避免外部依赖项,例如针对这种情况的事件中心和服务总线。

每秒发送很多消息,这将在必须调用 HTTP 时产生额外的开销,然后请求需要转换到 WebSocket 上下文。