1.服务敏感性

Service Fabric 群集资源管理器提供了移动成本接口,允许在针对均衡、碎片整理或其他要求进行移动时调整服务故障转移优先级。 然而,为了满足客户的需求,移动成本有一些局限性。 例如,移动成本无法明确优化单个移动,因为群集资源管理器 (CRM) 依赖于单个算法运行中所有移动的总分。 当 CRM 执行交换时,移动成本不起作用。 这是因为所有副本共享相同的交换成本,从而导致无法限制敏感副本的交换故障转移。 另一个限制是,移动成本仅提供四个可能的值(零、低、中、高)和一个特殊值(非常高)来调整副本的优先级。 这无法提供足够的灵活性来区分要进行故障转移的副本敏感度。

从 Service Fabric 版本 10.1 开始,CRM 引入了敏感度功能。 目前,此功能将服务与布尔变量 IsMaximumSensitivity 关联,表示服务副本是否为最敏感的副本。 CRM 为这些类型的副本提供针对故障转移的最大保护。 换句话说,如果服务的 IsMaximumSensitivity 设置为 true,则此服务的最高敏感度副本 (MSR) 只能在以下不可避免的情况下进行移动或交换:

  • 仅当 FD/UD 设置为硬约束时才违反 FD/UD 约束
  • 升级期间的副本交换
  • 节点上仅存在 MSR 时的节点容量冲突(即,如果节点上存在任何其他非 MSR,则 MSR 不可移动)。

例如,在表中列出的方案中,节点 1 处于节点容量冲突之下,因为节点负载为 150,超过了节点容量 100。 另一方面,节点 2 完全为空。 在这种情况下,这两个 MSR 都不可移动,因为非 MSR 会移动到节点 2 以修复冲突。

节点 节点负载/容量 MSR 服务 1 负载 MSR 服务 2 负载 非 MSR 服务负载
节点 1 150/100 50 50 50
节点 2 0/100

在以下情况下,两个负载为 60 的 MSR 在节点 1 上并置,导致节点 1 出现容量冲突。 节点 2 的空间为 80,其中只放置了一个非 MSR(负载 = 20)。 节点 1 上的其中一个 MSR 必须移动到节点 2,因为节点 1 上不存在要移动以修复冲突的非 MSR。

节点 节点负载/容量 MSR 服务 1 负载 MSR 服务 2 负载 非 MSR 服务负载
节点 1 120/100 60 60
节点 2 20/100 20

敏感度功能允许多个 MSR 在同一节点上并置。 不过,过多的 MSR 可能会导致节点容量冲突。 因此,与 IsMaximumSensitivity 一起,该功能将最大负载引入指标,以确保每个指标的最大负载之和小于或等于该指标的节点容量。 设置此上限后,CRM 可以安全地在同一节点上并置多个 MSR,从而避免了以下情况的发生,即只能通过移动最高敏感度副本来修复节点容量冲突。

假设为群集节点定义了两个客户指标:MetricA 和 MetricB。 MetricA 和 MetricB 的节点容量分别为 1004

下表显示了有关最高敏感度副本的并置的几个示例。 对于表中列出的三种方案,假设节点上已存在一个最高敏感度副本,并且MetricA 或 MetricB 的 MaxLoad 必须为正数。 是否可以在此节点上放置更多 MSR 取决于节点上剩余的空间和新 MSR 所需的资源。

  1. 只要它不会导致节点负载或 MaxLoad 容量冲突,就可以在此节点上放置更多 MSR。 (即 MetricA (Max)Load <= 50 && MetricB (Max)Load <= 2)。
  2. 无法在此节点上放置其他 MSR,因为 MetricA 和 MetricB 的 MaxLoad 均达到其节点 MaxLoad 容量。
  3. 尽管从 MetricA 的角度来看存在空间,但无法在此节点上放置其他 MSR,因为 MetricB 的 MaxLoad 达到其节点 MaxLoad 容量。
场景 # MetricA 负载 MetricB 负载 IsMaximumSensitivity MetricA MaxLoad MetricB MaxLoad 是否可以在此节点上放置另一个 MSR?
1 50 2 50 2
2 100 2 100 4
3 50 2 50 4

注意

当前敏感度功能仅提供 MSR 功能。 对于非 MSR(但具有不同的敏感度值),CRM 不会从敏感度的角度以不同的方式对待它们。

1.1. 启用/禁用服务敏感度

通过使用 XML 或 JSON 在群集清单的 PlacementAndLoadBalancing 部分中设置配置 EnableServiceSensitivity 来打开/关闭敏感度功能:

在 ClusterManifest.xml 中:

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

通过 ClusterConfig.json 进行独立部署或将 Template.json 用于 Azure 托管群集。

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

1.2. 设置服务敏感度

注意

尽管不需要将服务设置为最高敏感度服务,但建议设置相应的 MaximumLoad,以避免在同一节点上并置多个最高敏感度服务时溢出节点容量。 有关详细信息,请查看设置最大负载部分。

1.2.1. 使用应用程序清单

<Service>
  <StatefulService>
    <ServiceSensitivityDescription PrimaryDefaultSensitivity="0" SecondaryDefaultSensitivity="0" AuxiliaryDefaultSensitivity="0" IsMaximumSensitivity="True" />
  </StatefulService>
</Service>

1.2.2. 使用 PowerShell API

若要在创建服务时指定服务的敏感度,请执行以下操作:

$sensitivity = New-Object -TypeName System.Fabric.Description.ServiceSensitivityDescription
$sensitivity.PrimaryDefaultSensitivity = 0
$sensitivity.SecondaryDefaultSensitivity = 0
$sensitivity.AuxiliaryDefaultSensitivity = 0
$sensitivity.IsMaximumSensitivity = $true

New-ServiceFabricService -ApplicationName $applicationName -ServiceName $serviceName -ServiceTypeName $serviceTypeName -Stateful -MinReplicaSetSize 3 -TargetReplicaSetSize 3 -PartitionSchemeSingleton -ServiceSensitivityDescription $sensitivity

若要为现有服务动态指定或更新敏感度,请执行以下操作:

$sensitivity = New-Object -TypeName System.Fabric.Description.ServiceSensitivityDescription
$sensitivity.PrimaryDefaultSensitivity = 0
$sensitivity.SecondaryDefaultSensitivity = 0
$sensitivity.AuxiliaryDefaultSensitivity = 0
$sensitivity.IsMaximumSensitivity = $true

Update-ServiceFabricService -Stateful -ServiceName fabric:/AppName/ServiceName -ServiceSensitivityDescription $sensitivity

1.2.3. 使用 C# API

若要在创建服务时指定服务的敏感度,请执行以下操作:

FabricClient fabricClient = new FabricClient();

ServiceSensitivityDescription serviceSensitivity = new ServiceSensitivityDescription();
serviceSensitivity.PrimaryDefaultSensitivity = 0
serviceSensitivity.SecondaryDefaultSensitivity = 0
serviceSensitivity.AuxiliaryDefaultSensitivity = 0
serviceSensitivity.IsMaximumSensitivity = $true

StatefulServiceDescription serviceDescription = new StatefulServiceDescription();
serviceDescription.ServiceSensitivityDescription = serviceSensitivity; 

await fabricClient.ServiceManager.CreateServiceAsync(serviceDescription);

若要为现有服务动态指定或更新敏感度,请执行以下操作:

FabricClient fabricClient = new FabricClient();

ServiceSensitivityDescription serviceSensitivity = new ServiceSensitivityDescription();
serviceSensitivity.PrimaryDefaultSensitivity = 0
serviceSensitivity.SecondaryDefaultSensitivity = 0
serviceSensitivity.AuxiliaryDefaultSensitivity = 0
serviceSensitivity.IsMaximumSensitivity = $true

StatefulServiceUpdateDescription serviceUpdate = new StatefulServiceUpdateDescription();
serviceUpdate.ServiceSensitivityDescription = serviceSensitivity; 

await fabricClient.ServiceManager.UpdateServiceAsync(new Uri("fabric:/AppName/ServiceName"), serviceUpdate);

1.3. 设置最大负载

注意

MaximumLoad 的默认值为 0。 当为 MaximumLoad 指定正值时,用户首先需要将相应服务的 IsMaximumSensitivity 设置为 true。 另一个要求是 MaximumLoad 等于或大于同一指标中的所有默认负载。

1.3.1. 使用应用程序清单

<Service>
  <StatefulService>
    <SingletonPartition />
    <LoadMetrics>
      <LoadMetric Name="CPU" PrimaryDefaultLoad="10" SecondaryDefaultLoad="5" MaximumLoad="20" Weight="High" />
    </LoadMetrics>
  </StatefulService>
</Service>

1.3.2. 使用 PowerShell API

若要在创建服务时指定服务的最大负载,请执行以下操作:

New-ServiceFabricService -ApplicationName $applicationName -ServiceName $serviceName -ServiceTypeName $serviceTypeName -Stateful -MinReplicaSetSize 3 -TargetReplicaSetSize 3 -PartitionSchemeSingleton -Metric @("CPU,High,10,5,0,20")

若要指定或更新现有服务的最大负载,请执行以下操作:

Update-ServiceFabricService -Stateful -ServiceName fabric:/AppName/ServiceName -Metric @("CPU,High,10,5,0,20")

1.3.3. 使用 C# API

若要在创建服务时指定服务的敏感度,请执行以下操作:

FabricClient fabricClient = new FabricClient();

StatefulServiceLoadMetricDescription cpuMetric = new StatefulServiceLoadMetricDescription();
cpuMetric.Name = "CPU";
cpuMetric.PrimaryDefaultLoad = 10;
cpuMetric.SecondaryDefaultLoad = 5;
cpuMetric.AuxiliaryDefaultLoad = 0;
cpuMetric.Weight = ServiceLoadMetricWeight.High;
cpuMetric.MaximumLoad = 20;

StatefulServiceDescription serviceDescription = new StatefulServiceDescription();
serviceDescription.Metrics["CPU"] = cpuMetric;

await fabricClient.ServiceManager.CreateServiceAsync(serviceDescription);

若要指定或更新现有服务的最大负载,请执行以下操作:

FabricClient fabricClient = new FabricClient();

StatefulServiceLoadMetricDescription cpuMetric = new StatefulServiceLoadMetricDescription();
cpuMetric.Name = "CPU";
cpuMetric.PrimaryDefaultLoad = 10;
cpuMetric.SecondaryDefaultLoad = 5;
cpuMetric.AuxiliaryDefaultLoad = 0;
cpuMetric.Weight = ServiceLoadMetricWeight.High;
cpuMetric.MaximumLoad = 20;

StatefulServiceUpdateDescription updateDescription = new StatefulServiceUpdateDescription();
updateDescription.Metrics["CPU"] = cpuMetric;

await fabricClient.ServiceManager.UpdateServiceAsync(new Uri("fabric:/AppName/ServiceName"), updateDescription);

1.4. 后续步骤

详细了解服务移动成本