服务移动成本

尝试确定要对群集进行哪些更改时,Service Fabric 群集资源管理器考虑的一个因素是这些更改的成本。 “成本”这一概念根据能够改进的群集量而权衡。 移动服务以满足均衡、碎片整理和其他要求时,成本是一项考虑因素。 目标是以最稳妥或最便宜的方式满足这些要求。

移动服务可将 CPU 时间和网络带宽的成本降到最低。 对于有状态服务,需要复制消耗额外内存和磁盘的这些服务的状态。 将 Azure Service Fabric 群集资源管理器所提出的解决方案成本降到最低有助于避免使用不必要的群集资源。 但是,也不希望忽略可大幅改善群集中资源分配的解决方案。

群集资源管理器提供两种方式来计算和限制成本,同时尝试管理群集。 第一种机制只需计算它所进行的每次移动。 如果生成的两个解决方案的均衡值(分数)大致相同,则群集资源管理器倾向于采用成本(移动总量)最低的解决方案。

此策略适用。 但是,对于默认负载或静态负载,在任何复杂的系统中不太可能所有移动都一样。 有些移动的成本可能要昂贵得多。

设置移动成本

可在服务创建时为其指定默认的移动成本:

PowerShell:

New-ServiceFabricService -ApplicationName $applicationName -ServiceName $serviceName -ServiceTypeName $serviceTypeName -Stateful -MinReplicaSetSize 3 -TargetReplicaSetSize 3 -PartitionSchemeSingleton -DefaultMoveCost Medium

C#:

FabricClient fabricClient = new FabricClient();
StatefulServiceDescription serviceDescription = new StatefulServiceDescription();
//set up the rest of the ServiceDescription
serviceDescription.DefaultMoveCost = MoveCost.Medium;
await fabricClient.ServiceManager.CreateServiceAsync(serviceDescription);

此外,还可在服务创建后为该服务动态指定或更新 MoveCost:

PowerShell:

Update-ServiceFabricService -Stateful -ServiceName "fabric:/AppName/ServiceName" -DefaultMoveCost High

C#:

StatefulServiceUpdateDescription updateDescription = new StatefulServiceUpdateDescription();
updateDescription.DefaultMoveCost = MoveCost.High;
await fabricClient.ServiceManager.UpdateServiceAsync(new Uri("fabric:/AppName/ServiceName"), updateDescription);

动态指定每个副本的移动成本

前面的代码片段全部用于从服务本身外部同时指定整个服务的 MoveCost。 但是,当特定服务对象的移动成本在其生命周期内发生变化时,移动成本最为有用。 由于服务本身可能最了解移动给定时间的成本是多少,因此服务可以在运行时使用 API 来报告自己的移动成本。

C#:

this.Partition.ReportMoveCost(MoveCost.Medium);

注意

只能通过代码设置次要副本的移动成本。

报告分区的移动成本

上一部分介绍了服务副本或实例如何报告 MoveCost 本身。 我们提供 Service Fabric API 来代表其他分区报告 MoveCost 值。 有时,服务副本或实例无法单独确定最佳的 MoveCost 值,并且必须依赖于其他服务逻辑。 代表其他分区报告 MoveCost,并代表其他分区报告负载,这使你能够从外部完全管理分区。 从群集资源管理器的角度来看,这些 API 使你不再需要挎斗模式

你可以使用相同的 API 调用报告不同分区的 MoveCost 更新。 需要为每个要更新的 PartitionMoveCostDescription 对象指定 MoveCost 的新值。 API 可让你使用多种方法来更新 MoveCost:

  • 有状态服务分区可以更新其主要副本 MoveCost。
  • 无状态服务和有状态服务均可更新其所有次要副本或实例的 MoveCost。
  • 无状态服务和有状态服务均可更新节点上特定副本或实例的 MoveCost。

分区的每个 MoveCost 更新应至少包含一个要更改的有效值。 例如,你可以跳过主要副本更新,并将 null 分配到主副本条目,在 MoveCost 更新过程中将使用其他条目,并将跳过主要副本的 MoveCost 更新。 由于可以使用单个 API 调用更新多个分区的 MoveCost,因此 API 将为相应的分区提供返回代码列表。 如果我们成功接受并处理 MoveCost 更新的请求,则返回代码将为“成功”。 否则,API 将提供错误代码:

  • PartitionNotFound - 指定的分区 ID 不存在。
  • ReconfigurationPending - 分区目前正在重新配置。
  • InvalidForStatelessServices - 试图更改属于无状态服务的分区的主副本的 MoveCost。
  • ReplicaDoesNotExist - 指定的节点上不存在辅助副本或实例。
  • InvalidOperation - 为属于系统应用程序的分区更新 MoveCost。

C#:

Guid partitionId = Guid.Parse("53df3d7f-5471-403b-b736-bde6ad584f42");
string nodeName0 = "NodeName0";

OperationResult<UpdatePartitionMoveCostResultList> updatePartitionMoveCostResults =
    await this.FabricClient.UpdatePartitionMoveCostAsync(
        new UpdatePartitionMoveCostQueryDescription
        {
            new List<PartitionMoveCostDescription>()
            {
                new PartitionMoveCostDescription(
                    partitionId,
                    MoveCost.VeryHigh,
                    MoveCost.Zero,
                    new List<ReplicaMoveCostDescription>()
                    {
                        new ReplicaMoveCostDescription(nodeName0, MoveCost.Medium)
                    })
            }
        },
        this.Timeout,
        cancellationToken);

在此示例中,你将为分区 53df3d7f-5471-403b-b736-bde6ad584f42 更新最新报告的移动成本。 主要副本移动成本将为“VeryHigh”。 所有次要副本的移动成本将为“Zero”,但位于节点“NodeName0”上的特定次要副本的移动成本除外。 特定副本的移动成本将为“Medium”。 如果要跳过更新主要副本或所有次要副本的移动成本,可以将对应的条目保留为 null。

移动成本的影响

MoveCost 包含五个级别:Zero、Low、Medium、High 和 VeryHigh。 下列规则适用:

  • MoveCost 是相互的,但 Zero 和 VeryHigh 除外。
  • 零移动成本表示移动不会产生成本,不应计入解决方案的分数。
  • 将移动成本设置为 High 或 VeryHigh 并不能确保副本不会被移动。
  • 移动成本为 VeryHigh 的副本进行移动的前提是在群集中存在约束冲突,该冲突无法通过任何其他方式解决(即使需要移动许多其他的副本来解决冲突)

Move cost as a factor in selecting replicas for movement

MoveCost 可帮助我们在达成对等的均衡时,查找整体导致最少中断且最容易实现的解决方案。 服务的成本概念可以相对于许多事项。 计算移动成本时的最常见因素包括:

  • 服务必须移动的状态或数据量。
  • 客户端断开连接的成本。 移动主要副本的成本通常比移动次要副本的成本更高。
  • 中断某些进行中操作的成本。 某些数据存储级别的操作,或者为了响应客户端调用而执行的操作,成本都很高。 在特定的时间点后,除非有必要,否则我们不会停止这些操作。 因此,执行该操作时,将增加此服务对象的移动成本,以减小其移动的可能性。 当操作完成之后,可以将成本设置恢复正常。

重要

应慎重考虑使用 VeryHigh 移动成本,因为它会极大地限制群集资源管理器在群集中查找全局最佳放置解决方案的功能。 移动成本为 VeryHigh 的副本进行移动的前提是在群集中存在约束冲突,该冲突无法通过任何其他方式解决(即使需要移动许多其他的副本来解决冲突)

在群集中启用移动成本

为了考虑到更为精细的 MoveCost,必须在群集中启用 MoveCost。 如不进行此设置,则会使用计数移动的默认模式来计算 MoveCost,并忽略 MoveCost 报告。

ClusterManifest.xml:

<Section Name="PlacementAndLoadBalancing">
    <Parameter Name="UseMoveCostReports" Value="true" />
</Section>

通过用于独立部署的 ClusterConfig.json 或用于 Azure 托管群集的 Template.json:

"fabricSettings": [
  {
    "name": "PlacementAndLoadBalancing",
    "parameters": [
      {
          "name": "UseMoveCostReports",
          "value": "true"
      }
    ]
  }
]

后续步骤