我刚刚开始为我的 Service Fabric 应用程序编写一些动态端点发现,并正在寻找有关如何解析服务端点的示例。我在 stackoverflow 上找到了以下代码示例:
https://stackoverflow.com/a/38562986/4787510
我对此做了一些细微的改变,所以这是我的代码:
private readonly FabricClient m_fabricClient
public async Task RefreshEndpointList()
{
var appList = await m_fabricClient.QueryManager.GetApplicationListAsync();
var app = appList.Single(x => x.ApplicationName.ToString().Contains("<MyFabricDeploymentName>"));
// Go through all running services
foreach (var service in await m_fabricClient.QueryManager.GetServiceListAsync(app.ApplicationName))
{
var partitions = await m_fabricClient.QueryManager.GetPartitionListAsync(service.ServiceName);
// Go through all partitions
foreach (var partition in partitions)
{
// Check what kind of service we have - depending on that the resolver figures out the endpoints.
// E.g. Singleton is easy as it is just one endpoint, otherwise we need some load balancing later on
ServicePartitionKey key;
switch (partition.PartitionInformation.Kind)
{
case ServicePartitionKind.Singleton:
key = ServicePartitionKey.Singleton;
break;
case ServicePartitionKind.Int64Range:
var longKey = (Int64RangePartitionInformation)partition.PartitionInformation;
key = new ServicePartitionKey(longKey.LowKey);
break;
case ServicePartitionKind.Named:
var namedKey = (NamedPartitionInformation)partition.PartitionInformation;
key = new ServicePartitionKey(namedKey.Name);
break;
default:
throw new ArgumentOutOfRangeException($"Can't resolve partition kind for partition with id {partition.PartitionInformation.Id}");
}
var resolvedServicePartition = await ServicePartitionResolver.GetDefault().ResolveAsync(service.ServiceName, key, CancellationToken.None);
m_endpointCache.PutItem(service.ServiceTypeName, new ServiceDetail(service.ServiceTypeName, service.ServiceKind, ServicePartitionKind.Int64Range, resolvedServicePartition.Endpoints));
}
}
}
}
我很高兴找到了这个片段,但是在研究它的过程中,我发现了一件事让我有点困惑。
所以,在阅读了 SF 文档之后,据我了解,这似乎是它从上到下遵循的架构:
Service Fabric 集群 -> Service Fabric 应用程序(例如 myApp_Fabric) -> 服务(例如前端服务、个人资料图片微服务、后端服务)
从服务中我们可以深入到分区,而分区基本上类似于集群中节点上的“容器”,其中可以驻留多个实例(副本),实例是服务的实际部署。
不过,我不太确定节点/分区/副本差异是否正确。
但是,回到我的困惑和实际问题:
为什么有关分区策略(singleton、intRange、named)的信息附加到分区信息中,而不是服务本身?据我了解,分区基本上是我如何将服务配置为跨服务结构节点分布的产物。
那么,为什么分区策略不直接与服务绑定(bind)?
最佳答案
关于Service Fabric中的服务,有两种类型:有状态服务和无状态服务。
无状态服务不使用可靠集合来处理状态。如果它们需要维护状态,则必须依赖外部持久性解决方案,例如数据库等。由于它们不处理可靠集合提供的状态,因此它们被分配了 Singelton 分区类型。
有状态服务能够将状态存储在可靠的集合中。为了能够扩展这些服务,这些集合中的数据应该按分区进行划分。每个服务实例都分配有一个特定的分区。每个服务指定分区数量,如下例所示:
<Service Name="Processing">
<StatefulService ServiceTypeName="ProcessingType" TargetReplicaSetSize="3" MinReplicaSetSize="3">
<UniformInt64Partition PartitionCount="26" LowKey="0" HighKey="25" />
</StatefulService>
</Service>
因此,鉴于上面的示例,我不明白您最后关于分区策略不直接与服务绑定(bind)的评论。
鉴于上述情况,该服务将有 26 个实例运行,每个分区一个,乘以副本数量。
如果是无状态服务,则只有一个分区(单例分区),因此实际实例数为 1 * 3(副本数)= 3。(3 个副本只是一个示例。大多数情况下无状态服务的实例计数设置为 -1,即集群中每个节点有 1 个实例。)
另一件事:在您的代码中,您在代码迭代分区中有一个注释行:
// E.g. Singleton is easy as it is just one endpoint, otherwise we need some load balancing later on
此评论错误地指出分区与负载平衡有关。事实并非如此,它与数据在服务实例上的分区方式有关,并且您需要获取处理特定分区的服务的地址。假设我有一个包含 26 个分区的服务,我想获取存储在第 5 个分区中的数据。然后,我需要获取为该分区提供服务的实例的端点。
您可能已经阅读过 the docs 。如果没有,我建议您也阅读一下。
处理您的评论:
I was just wondering, is it not possible that multiple services run on the same partition?
可靠集合与使用它们的服务耦合,底层分区也是如此。因此,同一分区上不能运行多个服务。
但是,服务实例可以。如果某个服务的副本大小为 3,则将有 3 个实例为该分区提供服务。但只有 1 个是主实例,负责读取和写入复制到辅助实例的数据。
关于azure - 为什么 Service Fabric 服务的分区策略与分区而不是服务相关?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55558066/