从分区 ID 确定分区键(名称或编号范围)

Determine partition key (name or number range) from partition ID

对于有状态服务,副本是否可以通过其分区 ID(GUID 值)确定分区键(字符串或 number/number 范围)?查看 .NET API,只能从 ServicePartitionKey 获取副本 ID,反之则不行。

不,您无法直接从分区 ID (guid) 获取它。根据您使用的分区类型(Singleton、Int64Range 或 Named)以及设置方式,可能 派生它 ,但无法直接从服务进行。

这样做是有道理的,请考虑这样一种情况,您的服务具有 low key = 0high key = 9 以及 2 个分区的 Int64 分区方案。从 0 到 4 的任何分区键都将在分区号上结束。分区号上的 1 和键 5 - 9 2. 但是由于任何使用 0 到 4 键的调用都会在该服务的 相同实例 上结束,因此键实际上是 per call,而不是 per service,所以从服务的角度来看,它如何知道它的分区对应于哪个键,除非那是客户端调用服务的东西,你可以说 "for this call to partition XXX the key is 123"。目前没有这样的信息融入到结构传输通信中,分区在客户端解析,从未传递给服务。

您可以做的是找出分区 ID 所在的范围。对于单例分区方案,您在 'the partition' 上,这里没有更多讨论。对于 Named 和 Int64,您可以使用 FabricClient.QueryManager 枚举分区:

var fabricClient = new FabricClient();
var partitionList = await fabricClient.QueryManager.GetPartitionListAsync(serviceName);

foreach (var partition in partitionList)
{
    // Partition Guid
    var partitionId = partition.PartitionInformation.Id;

    // Int 64 Range
    var int64PartitionInfo = partition.PartitionInformation as Int64RangePartitionInformation;
    var lowKey = int64PartitionInfo?.LowKey;
    var highKey = int64PartitionInfo?.HighKey;

    // Named Range
    var namedPartitionInfo = partition.PartitionInformation as NamedPartitionInformation;
    var name = namedPartitionInfo.Name;
}

对于命名范围 if 实际上确实为您提供了分区键,因为它是那里的 one-to-one 映射,但对于 Int64 范围,您将只能获得该分区的整数范围。

上面的代码也是您可能不希望每次要查找分区键时 运行 因为 FabricClient.QueryManager 相对较慢。

如果知道每次服务调用中的分区键对您来说很重要,那么您还有另一个选择,就是将其作为消息参数或消息头添加到您对客户端的调用中(类似对此 )

yoape 回答的真好,应该从客户端需要从服务外部知道分区信息的场景考虑。但它表明从服务本身内部是不可能的。

根据问题,它要求从服务本身内部获取此信息,并且可以获取如下分区信息。

假设您有这样的 StatefulService:

class WorkerService : StatefulService {}

在该服务中,您可以获得这样的分区信息:

switch (this.Partition.PartitionInfo.Kind)
{
    case ServicePartitionKind.Int64Range:
        var rangePartition = this.Partition.PartitionInfo as Int64RangePartitionInformation;
        var lowKey = rangePartition.LowKey;
        var highKey = rangePartition.HighKey;
        break;
    case ServicePartitionKind.Named:
        var namedPartition = this.Partition.PartitionInfo as NamedPartitionInformation;
        var name = namedPartition.Name;
        break;
    case ServicePartitionKind.Singleton:
        var singleton = this.Partition.PartitionInfo as SingletonPartitionInformation;
        var PartitionId = singleton.Id;
        break; 
    default:
        var PartitionId2 = this.Partition.PartitionInfo.Id;
        break;
}

单例与默认相同,都使用分区的 id。