Compartilhar via


Custo do movimentação de serviços

Um fator que o Gerenciador de Recursos de Cluster do Service Fabric considera ao tentar determinar quais alterações fazer em um cluster é o custo dessas alterações. A noção de "custo" é avaliada considerando quanto o cluster pode ser melhorado. O custo é considerado ao mover serviços para balanceamento, desfragmentação e outros requisitos. A meta é atender aos requisitos da maneira menos perturbadora ou cara.

Movimentar serviços custa, no mínimo, tempo de CPU e largura de banda de rede. Para serviços com estado, é necessário copiar o estado desses serviços, consumindo mais disco e memória. Minimizar o custo das soluções que o Gerenciador de Recursos de Cluster do Azure Service Fabric oferece ajuda a garantir que recursos do cluster não sejam gastos desnecessariamente. No entanto, não seria bom ignorar soluções que melhorariam significativamente a alocação de recursos no cluster.

O Gerenciador de Recursos de Cluster tem duas maneiras de calcular custos e limitá-los, enquanto tenta gerenciar o cluster. O primeiro mecanismo é simplesmente contar cada movimentação que seria feita. Se duas soluções forem geradas com quase o mesmo saldo (pontuação), o Gerenciador de Recursos de Cluster preferirá a que tem o custo mais baixo (número total de movimentações).

Esta estratégia funciona bem. Mas, como ocorre com cargas estáticas ou padrão, é improvável em qualquer sistema complexo que todas as mudanças sejam iguais. É provável que algumas delas sejam muito mais caras.

Definindo custos de movimentação

Você pode especificar o custo de movimentação padrão para um serviço quando ele é criado:

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);

Você também pode especificar ou atualizar MoveCost dinamicamente para um serviço após ele ter sido criado:

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);

Especificando dinamicamente o custo de movimentação por réplica

Os snippets de código anteriores são todos voltados a especificar MoveCost para um serviço inteiro de uma vez, de fora do próprio serviço. No entanto, o custo de movimentação é mais útil quando muda ao longo do tempo de vida de um objeto de serviço específico. Como os próprios serviços provavelmente sabem melhor qual é o custo de sua movimentação em um determinado momento, há uma API para os serviços relatarem seu próprio custo de movimentação individual durante o runtime.

C#:

this.Partition.ReportMoveCost(MoveCost.Medium);

Observação

Só é possível definir o custo de movimentação de réplicas secundárias por meio de código.

Como reportar o custo de movimentação para uma partição

A seção anterior descreve como as próprias réplicas ou instâncias de serviço reportam os MoveCost. Nós fornecemos a API do Service Fabric para reportar os valores de MoveCost em nome de outras partições. Às vezes, a réplica ou instância do serviço não consegue determinar o melhor valor de MoveCost por si só e precisa contar com outras lógicas de serviços. Reportar o MoveCost em nome de outras partições, juntamente com a carga de relatórios em nome de outras partições, permite que você gerencie completamente as partições de fora. Essas APIs eliminam as necessidades do padrão Sidecar, da perspectiva do Gerenciador de Recursos de Cluster.

Você pode relatar as atualizações do MoveCost para uma partição diferente com a mesma chamada à API. Você precisa especificar o objeto PartitionMoveCostDescription para cada partição que deseja atualizar com os novos valores de MoveCost. A API permite várias maneiras de atualizar o MoveCost:

  • Uma partição de serviço com estado pode atualizar o MoveCost da réplica primária dela.
  • Tanto serviços com estado quanto serviços sem estado podem atualizar o MoveCost de todas as instâncias ou réplicas secundárias.
  • Tanto serviços com estado quanto serviços sem estado podem atualizar o MoveCost de uma réplica ou instância específica em um nó.

Cada atualização de MoveCost para a partição deve conter pelo menos um valor válido que será alterado. Por exemplo, você pode ignorar a atualização da réplica primária com a atribuição de nulo à entrada dela; então outras entradas serão usadas durante a atualização do MoveCost e ignoraremos a atualização do MoveCost para a réplica primária. Como é possível atualizar o MoveCost para várias partições com apenas uma chamada à API, a API fornece uma lista de códigos de retorno para a partição correspondente. Se aceitarmos e processarmos uma solicitação de atualização de MoveCost com sucesso, o código de retorno será bem-sucedido. Caso contrário, a API fornece o código de erro:

  • PartitionNotFound – a ID da partição especificada não existe.
  • ReconfigurationPending – a partição está sendo reconfigurada no momento.
  • InvalidForStatelessServices – Foi feita uma tentativa de alterar o MoveCost de uma réplica primária de uma partição que pertence a um serviço sem estado.
  • ReplicaDoesNotExist – a réplica ou instância secundária não existe em um nó especificado.
  • InvalidOperation – Atualização do MoveCost para uma partição que pertence ao aplicativo do sistema.

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);

Com este exemplo, você executará uma atualização do último MovCost registrado de uma partição 53df3d7f-5471-403b-b736-bde6ad584f42. O custo de movimentação da réplica primária será VeryHigh. O custo de movimentação de todas as réplicas secundárias será zero, exceto de uma réplica secundária específica localizada no nó NodeName0. O custo de movimentação para uma réplica específica será Medium. Se desejar ignorar a atualização do custo de movimentação para a réplica primária ou para todas as réplicas secundárias, você poderá deixar a entrada correspondente com o valor nulo.

Impacto do custo de movimentação

MoveCost tem cinco níveis: Zero, Low, Medium, High e VeryHigh. As seguintes regras se aplicam:

  • MoveCosts têm relação uns com os outros, exceto por Zero e VeryHigh.
  • O custo de movimentação Zero significa que a movimentação é gratuita e não deve contar na pontuação da solução.
  • Definir o custo de movimentação como High ou VeryHigh não garante que a réplica nunca será movida.
  • Réplicas com custo de movimentação VeryHigh serão movidas somente se houver uma violação de restrição no cluster que não possa ser corrigida de nenhuma outra maneira (mesmo que seja necessária a movimentação de muitas outras réplicas para corrigir a violação)

O custo de movimentação como um fator na seleção de réplicas para movimentação

O MoveCost ajuda a encontrar as soluções que causam, em geral, o mínimo de interrupções e que sejam mais fáceis de conseguir enquanto ainda alcançam o equilíbrio equivalente. A noção de custo de um serviço pode ser relativa a muitas coisas. Os fatores mais comuns ao calcular o custo do movimento são:

  • a quantidade de estados ou de dados que o serviço deve mover.
  • o custo de desconexão de clientes. O custo de movimentar uma réplica primária normalmente é mais alto do que o custo de movimentar uma réplica secundária.
  • o custo de interromper uma operação em andamento. Algumas operações no nível do armazenamento de dados ou operações realizadas em resposta a uma chamada de cliente são caras. Depois de um certo ponto, você não quer interrompê-las a não ser que seja necessário. Assim, enquanto a operação estiver em andamento, você aumenta o custo de movimentação desse objeto de serviço para reduzir a probabilidade de que ele se mova. Quando a operação estiver concluída, defina o custo de volta para normal.

Importante

O uso do custo de movimentação VeryHigh deve ser considerado com atenção, pois restringe significativamente a capacidade do Gerenciador de Recursos de Cluster de encontrar uma solução de posicionamento globalmente ideal no cluster. Réplicas com custo de movimentação VeryHigh serão movidas somente se houver uma violação de restrição no cluster que não possa ser corrigida de nenhuma outra maneira (mesmo que seja necessária a movimentação de muitas outras réplicas para corrigir a violação)

Habilitando o custo de movimentação em seu cluster

Para que os MoveCosts mais granulares sejam levados em conta, MoveCost deve estar habilitado em seu cluster. Sem essa configuração, o modo padrão de contar movimentações é usado para calcular MoveCost e relatórios de MoveCost são ignorados.

ClusterManifest.xml:

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

via ClusterConfig.json para implantações Autônomas ou Template.json para clusters hospedados pelo Azure:

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

Próximas etapas