Ações de testabilidade

Para simular uma infraestrutura pouco fiável, o Azure Service Fabric fornece-lhe, o programador, formas de simular várias falhas do mundo real e transições de estado. Estas são expostas como ações de testability. As ações são as APIs de baixo nível que causam uma injeção de falhas específica, transição de estado ou validação. Ao combinar estas ações, pode escrever cenários de teste abrangentes para os seus serviços.

O Service Fabric fornece alguns cenários de teste comuns compostos por estas ações. Recomendamos vivamente que utilize estes cenários incorporados, que são cuidadosamente escolhidos para testar transições de estado comuns e casos de falha. No entanto, as ações podem ser utilizadas para criar cenários de teste personalizados quando pretende adicionar cobertura para cenários que ainda não estão abrangidos pelos cenários incorporados ou que são personalizados para a sua aplicação.

As implementações C# das ações encontram-se na assemblagem System.Fabric.dll. O módulo do PowerShell do System Fabric encontra-se na assemblagem Microsoft.ServiceFabric.Powershell.dll. Como parte da instalação do runtime, o módulo ServiceFabric PowerShell é instalado para permitir a facilidade de utilização.

Ações de falha graciosas vs. ingrates

As ações de testabilidade são classificadas em dois principais registos:

  • Falhas incorretas: estas falhas simulam falhas como reinícios do computador e falhas de processos. Nestes casos de falhas, o contexto de execução do processo para abruptamente. Isto significa que não é possível executar nenhuma limpeza do estado antes de a aplicação começar novamente.
  • Falhas graciosas: estas falhas simulam ações corretas, como movimentos de réplica e quedas acionadas pelo balanceamento de carga. Nesses casos, o serviço recebe uma notificação do fecho e pode limpar o estado antes de sair.

Para uma validação de melhor qualidade, execute o serviço e a carga de trabalho empresarial ao mesmo tempo que induz várias falhas graciosas e ingratas. Cenários de exercício de falhas incorretos em que o processo de serviço sai abruptamente no meio de algum fluxo de trabalho. Isto testa o caminho de recuperação assim que a réplica do serviço for restaurada pelo Service Fabric. Isto ajudará a testar a consistência dos dados e se o estado do serviço é mantido corretamente após falhas. O outro conjunto de falhas (as falhas corretas) testa que o serviço reage corretamente às réplicas que estão a ser movidas pelo Service Fabric. Isto testa o processamento do cancelamento no método RunAsync. O serviço tem de verificar se o token de cancelamento está a ser definido, guardar corretamente o estado e sair do método RunAsync.

Lista de ações de testabilidade

Ação Descrição API Gerida Cmdlet do PowerShell Falhas graciosas/ingratas
CleanTestState Remove todo o estado de teste do cluster em caso de encerramento incorreto do controlador de teste. CleanTestStateAsync Remove-ServiceFabricTestState Não aplicável
InvokeDataLoss Induz a perda de dados numa partição de serviço. InvokeDataLossAsync Invoke-ServiceFabricPartitionDataLoss Gracioso
InvokeQuorumLoss Coloca uma determinada partição de serviço com estado em perda de quórum. InvokeQuorumLossAsync Invoke-ServiceFabricQuorumLoss Gracioso
MoverPrimário Move a réplica primária especificada de um serviço com estado para o nó de cluster especificado. MoverPrimaryAsync Move-ServiceFabricPrimaryReplica Gracioso
MoveSecondary Move a réplica secundária atual de um serviço com estado para um nó de cluster diferente. MoveSecondaryAsync Move-ServiceFabricSecondaryReplica Gracioso
MoveInstance Move a instância atual de um serviço sem estado para um nó de cluster diferente. MoveInstanceAsync Move-ServiceFabricInstance Gracioso
RemoverReplica Simula uma falha de réplica ao remover uma réplica de um cluster. Esta ação irá fechar a réplica e transitá-la para a função "Nenhum", removendo todo o estado do cluster. RemoverReplicaAsync Remove-ServiceFabricReplica Gracioso
RestartDeployedCodePackage Simula uma falha no processo do pacote de código ao reiniciar um pacote de código implementado num nó num cluster. Isto aborta o processo do pacote de código, que irá reiniciar todas as réplicas do serviço de utilizador alojadas nesse processo. RestartDeployedCodePackageAsync Restart-ServiceFabricDeployedCodePackage Incorreto
RestartNode Simula uma falha do nó de cluster do Service Fabric ao reiniciar um nó. RestartNodeAsync Restart-ServiceFabricNode Incorreto
RestartPartition Simula um cenário de apagão do datacenter ou de apagão do cluster ao reiniciar algumas ou todas as réplicas de uma partição. RestartPartitionAsync Restart-ServiceFabricPartition Gracioso
ReiniciarReplica Simula uma falha de réplica ao reiniciar uma réplica persistente num cluster, fechar a réplica e, em seguida, voltar a abri-la. RestartReplicaAsync Restart-ServiceFabricReplica Gracioso
StartNode Inicia um nó num cluster que já está parado. StartNodeAsync Start-ServiceFabricNode Não aplicável
StopNode Simula uma falha de nó ao parar um nó num cluster. O nó permanecerá inativo até o StartNode ser chamado. StopNodeAsync Stop-ServiceFabricNode Incorreto
ValidateApplication Valida a disponibilidade e o estado de funcionamento de todos os serviços do Service Fabric numa aplicação, normalmente após induzir alguma falha no sistema. ValidateApplicationAsync Test-ServiceFabricApplication Não aplicável
ValidateService Valida a disponibilidade e o estado de funcionamento de um serviço do Service Fabric, normalmente após induzir alguma falha no sistema. ValidateServiceAsync Test-ServiceFabricService Não aplicável

Executar uma ação de capacidade de teste com o PowerShell

Este tutorial mostra-lhe como executar uma ação de capacidade de teste com o PowerShell. Irá aprender a executar uma ação de teste num cluster local (de uma caixa) ou num cluster do Azure. Microsoft.Fabric.Powershell.dll - o módulo do PowerShell do Service Fabric - é instalado automaticamente quando instala o MSI do Microsoft Service Fabric. O módulo é carregado automaticamente quando abre uma linha de comandos do PowerShell.

Segmentos de tutoriais:

Executar uma ação num cluster de uma caixa

Para executar uma ação de testabilidade num cluster local, ligue-se primeiro ao cluster e abra a linha de comandos do PowerShell no modo de administrador. Vejamos a ação Restart-ServiceFabricNode .

Restart-ServiceFabricNode -NodeName Node1 -CompletionMode DoNotVerify

Aqui, a ação Restart-ServiceFabricNode está a ser executada num nó com o nome "Node1". O modo de conclusão especifica que não deve verificar se a ação restart-node foi realmente bem-sucedida. Especificar o modo de conclusão como "Verificar" fará com que verifique se a ação de reinício foi realmente bem-sucedida. Em vez de especificar diretamente o nó pelo respetivo nome, pode especificá-lo através de uma chave de partição e do tipo de réplica, da seguinte forma:

Restart-ServiceFabricNode -ReplicaKindPrimary  -PartitionKindNamed -PartitionKey Partition3 -CompletionMode Verify
$connection = "localhost:19000"
$nodeName = "Node1"

Connect-ServiceFabricCluster $connection
Restart-ServiceFabricNode -NodeName $nodeName -CompletionMode DoNotVerify

Restart-ServiceFabricNode deve ser utilizado para reiniciar um nó do Service Fabric num cluster. Isto irá parar o processo de Fabric.exe, que irá reiniciar todas as réplicas do serviço de sistema e do serviço de utilizador alojadas nesse nó. Utilizar esta API para testar o seu serviço ajuda a descobrir erros ao longo dos caminhos de recuperação de ativação pós-falha. Ajuda a simular falhas de nós no cluster.

A seguinte captura de ecrã mostra o comando restart-ServiceFabricNode em ação.

Captura de ecrã a mostrar a execução do comando Restart-ServiceFabricNode no PowerShell.

O resultado do primeiro Get-ServiceFabricNode (um cmdlet do módulo PowerShell do Service Fabric) mostra que o cluster local tem cinco nós: Node.1 a Node.5. Após a ação de teste (cmdlet) Restart-ServiceFabricNode ser executada no nó, com o nome Node.4, vemos que o tempo de atividade do nó foi reposto.

Executar uma ação num cluster do Azure

A execução de uma ação de teste (com o PowerShell) num cluster do Azure é semelhante à execução da ação num cluster local. A única diferença é que, antes de poder executar a ação, em vez de ligar ao cluster local, primeiro tem de se ligar ao cluster do Azure.

Executar uma ação de capacidade de teste com C #

Para executar uma ação de testabilidade com C#, primeiro tem de se ligar ao cluster com FabricClient. Em seguida, obtenha os parâmetros necessários para executar a ação. Podem ser utilizados parâmetros diferentes para executar a mesma ação. Ao observar a ação RestartServiceFabricNode, uma forma de executá-la é através das informações do nó (nome do nó e ID da instância do nó) no cluster.

RestartNodeAsync(nodeName, nodeInstanceId, completeMode, operationTimeout, CancellationToken.None)

Explicação do parâmetro:

  • CompleteMode especifica que o modo não deve verificar se a ação de reinício foi realmente bem-sucedida. Especificar o modo de conclusão como "Verificar" fará com que verifique se a ação de reinício foi realmente bem-sucedida.
  • OperationTimeout define a quantidade de tempo para a operação ser concluída antes de ser emitida uma exceção TimeoutException.
  • CancellationToken permite que uma chamada pendente seja cancelada.

Em vez de especificar diretamente o nó pelo respetivo nome, pode especificá-lo através de uma chave de partição e do tipo de réplica.

Para obter mais informações, veja PartitionSelector e ReplicaSelector.

// Add a reference to System.Fabric.Testability.dll and System.Fabric.dll
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Fabric.Testability;
using System.Fabric;
using System.Threading;
using System.Numerics;

class Test
{
    public static int Main(string[] args)
    {
        string clusterConnection = "localhost:19000";
        Uri serviceName = new Uri("fabric:/samples/PersistentToDoListApp/PersistentToDoListService");
        string nodeName = "N0040";
        BigInteger nodeInstanceId = 130743013389060139;

        Console.WriteLine("Starting RestartNode test");
        try
        {
            //Restart the node by using ReplicaSelector
            RestartNodeAsync(clusterConnection, serviceName).Wait();

            //Another way to restart node is by using nodeName and nodeInstanceId
            RestartNodeAsync(clusterConnection, nodeName, nodeInstanceId).Wait();
        }
        catch (AggregateException exAgg)
        {
            Console.WriteLine("RestartNode did not complete: ");
            foreach (Exception ex in exAgg.InnerExceptions)
            {
                if (ex is FabricException)
                {
                    Console.WriteLine("HResult: {0} Message: {1}", ex.HResult, ex.Message);
                }
            }
            return -1;
        }

        Console.WriteLine("RestartNode completed.");
        return 0;
    }

    static async Task RestartNodeAsync(string clusterConnection, Uri serviceName)
    {
        PartitionSelector randomPartitionSelector = PartitionSelector.RandomOf(serviceName);
        ReplicaSelector primaryofReplicaSelector = ReplicaSelector.PrimaryOf(randomPartitionSelector);

        // Create FabricClient with connection and security information here
        FabricClient fabricclient = new FabricClient(clusterConnection);
        await fabricclient.FaultManager.RestartNodeAsync(primaryofReplicaSelector, CompletionMode.Verify);
    }

    static async Task RestartNodeAsync(string clusterConnection, string nodeName, BigInteger nodeInstanceId)
    {
        // Create FabricClient with connection and security information here
        FabricClient fabricclient = new FabricClient(clusterConnection);
        await fabricclient.FaultManager.RestartNodeAsync(nodeName, nodeInstanceId, CompletionMode.Verify);
    }
}

PartitionSelector e ReplicaSelector

PartitionSelector

PartitionSelector é um programa auxiliar exposto na capacidade de teste e é utilizado para selecionar uma partição específica na qual realizar qualquer uma das ações de teste. Pode ser utilizado para selecionar uma partição específica se o ID da partição for conhecido previamente. Em alternativa, pode fornecer a chave de partição e a operação irá resolver o ID da partição internamente. Também tem a opção de selecionar uma partição aleatória.

Para utilizar este programa auxiliar, crie o objeto PartitionSelector e selecione a partição com um dos métodos Select*. Em seguida, transmita o objeto PartitionSelector para a API que o requer. Se não estiver selecionada nenhuma opção, a predefinição é uma partição aleatória.

Uri serviceName = new Uri("fabric:/samples/InMemoryToDoListApp/InMemoryToDoListService");
Guid partitionIdGuid = new Guid("8fb7ebcc-56ee-4862-9cc0-7c6421e68829");
string partitionName = "Partition1";
Int64 partitionKeyUniformInt64 = 1;

// Select a random partition
PartitionSelector randomPartitionSelector = PartitionSelector.RandomOf(serviceName);

// Select a partition based on ID
PartitionSelector partitionSelectorById = PartitionSelector.PartitionIdOf(serviceName, partitionIdGuid);

// Select a partition based on name
PartitionSelector namedPartitionSelector = PartitionSelector.PartitionKeyOf(serviceName, partitionName);

// Select a partition based on partition key
PartitionSelector uniformIntPartitionSelector = PartitionSelector.PartitionKeyOf(serviceName, partitionKeyUniformInt64);

ReplicaSelector

ReplicaSelector é um programa auxiliar exposto na capacidade de teste e é utilizado para ajudar a selecionar uma réplica na qual realizar qualquer uma das ações de teste. Pode ser utilizado para selecionar uma réplica específica se o ID de réplica for conhecido de antemão. Além disso, tem a opção de selecionar uma réplica primária ou uma secundária aleatória. ReplicaSelector deriva de PartitionSelector, pelo que tem de selecionar a réplica e a partição na qual pretende executar a operação de teste.

Para utilizar este programa auxiliar, crie um objeto ReplicaSelector e defina a forma como pretende selecionar a réplica e a partição. Em seguida, pode passá-lo para a API que a exige. Se não estiver selecionada nenhuma opção, a predefinição é uma réplica aleatória e uma partição aleatória.

Guid partitionIdGuid = new Guid("8fb7ebcc-56ee-4862-9cc0-7c6421e68829");
PartitionSelector partitionSelector = PartitionSelector.PartitionIdOf(serviceName, partitionIdGuid);
long replicaId = 130559876481875498;

// Select a random replica
ReplicaSelector randomReplicaSelector = ReplicaSelector.RandomOf(partitionSelector);

// Select the primary replica
ReplicaSelector primaryReplicaSelector = ReplicaSelector.PrimaryOf(partitionSelector);

// Select the replica by ID
ReplicaSelector replicaByIdSelector = ReplicaSelector.ReplicaIdOf(partitionSelector, replicaId);

// Select a random secondary replica
ReplicaSelector secondaryReplicaSelector = ReplicaSelector.RandomSecondaryOf(partitionSelector);

Passos seguintes