我在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个有状态的actor。要聚合计数器信息,我们需要联系所有服务分区和actor-instances。
我们当然可以撤消它,并让每个人都发送到那里计算一个(分区)服务。但是这会在正常流程中添加网络调用(从而增加开销)。
相反,我们想出了以下内容。所提到的服务和参与者被组合成一个可执行文件和一个服务显示器。因此它们处于相同的过程中。我们使用instancecount -1向所提到的服务和演员添加无状态服务。所有计数器信息都存储在静态变量中。无状态服务可以读取此计数器信息。 现在,我们只需要接触无状态服务(具有节点数量的上限)。
答案 0 :(得分:3)
为了首先获得一些术语,“replica”仅适用于有状态服务,其中您为服务的每个分区设置了唯一的副本集,并在它们之间为HA复制状态。无状态服务只有实例,所有实例都是相同和相同的。
现在回答您的实际问题:ServiceProxy没有连接到已部署无状态服务的特定实例的选项。您有以下选择:
E.g:
ServiceProxy.Create<IMyService>(serviceUri, partitionKey, TargetReplicaSelector.RandomInstance)
那为什么没有连接到特定无状态服务实例的选项呢?
好吧,我会转过这个问题并问你为什么想要连接到特定的无状态服务实例?根据定义,每个无状态实例应该是相同的。如果你在那里保持一些状态 - 比如用户会话 - 那么现在你是有状态的,应该使用有状态服务。
您可能会想到智能地决定连接到哪个实例以进行负载平衡,但是因为它是无状态的,所以只要请求均匀分布,任何实例都不应该做任何其他工作。为此,Service Proxy具有随机分发选项。
考虑到这一点,如果你还有一些理由寻找特定的无状态服务实例,你总是可以使用不同的通信堆栈 - 比如HTTP - 并做任何你想做的事。
答案 1 :(得分:1)
“好吧,我会转过这个问题并询问您为什么要连接到特定的无状态服务实例?”
一个例子是,如果您有多个(3x)无状态服务实例都具有到不同客户端的WebSocket连接,那么就说500个。并且你想要通知所有1500(500x3)用户相同的消息,如果可以直接连接到特定的实例(我可以预期这是可能的,因为我可以使用FabricClient查询这些实例),我可以发送向每个实例发送一条消息,将其重定向到所有连接的客户端。
相反,我们必须提出多种解决方法中的任何一种:
让所有实例连接到一些允许它们触发传入消息的事件系统,例如: Azure事件中心,Azure Service Bus,RedisCache。
如此处所述,托管另一个端点,使其成为服务实例的3个端点:WCF,WebSocket,HTTP。
更改为有状态分区服务,该服务不包含任何状态或任何副本,但只允许调用分区。
目前RedisCache存在一些严重问题,因此需要远离它,并希望避免外部依赖,例如事件中心和服务总线,仅适用于此场景。
每秒发送许多消息,这将在必须调用HTTP时产生额外的开销,然后请求需要转换到WebSocket上下文。