Ações de testabilidade

Para simular uma infraestrutura não confiável, o Azure Service Fabric fornece a você, desenvolvedor, maneiras de simular várias falhas do mundo real e transições de estado. Estes são expostos como ações de testabilidade. As ações são as APIs de baixo nível que causam uma injeção de falha específica, transição de estado ou validação. Ao combinar essas ações, você pode escrever cenários de teste abrangentes para seus serviços.

O Service Fabric fornece alguns cenários de teste comuns compostos por essas ações. É altamente recomendável que você utilize esses cenários internos, que são cuidadosamente escolhidos para testar transições de estado comuns e casos de falha. No entanto, as ações podem ser usadas para criar cenários de teste personalizados quando você deseja adicionar cobertura para cenários que ainda não são cobertos pelos cenários internos ou que são personalizados para seu aplicativo.

As implementações em C# das ações são encontradas no assembly System.Fabric.dll. O módulo PowerShell do System Fabric é encontrado no assembly Microsoft.ServiceFabric.Powershell.dll. Como parte da instalação em tempo de execução, o módulo PowerShell do ServiceFabric é instalado para permitir facilidade de uso.

Ações de culpa graciosas vs. ingraciosas

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

  • Falhas desgraçadas: essas falhas simulam falhas como reinicializações de máquinas e falhas de processos. Nesses casos de falhas, o contexto de execução do processo para abruptamente. Isso significa que nenhuma limpeza do estado pode ser executada antes que o aplicativo seja iniciado novamente.
  • Falhas graciosas: essas falhas simulam ações graciosas, como movimentos de réplica e quedas desencadeados pelo balanceamento de carga. Nesses casos, o serviço recebe uma notificação do fechamento e pode limpar o estado antes de sair.

Para uma validação de melhor qualidade, execute o serviço e a carga de trabalho de negócios enquanto induz várias falhas graciosas e desgraçadas. Falhas irregulares exercitam cenários em que o processo de serviço sai abruptamente no meio de algum fluxo de trabalho. Isso testa o caminho de recuperação depois que a réplica de serviço é restaurada pelo Service Fabric. Isso 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 normais) testa se o serviço reage corretamente às réplicas que estão sendo movidas pelo Service Fabric. Isso testa a manipulação do cancelamento no método RunAsync. O serviço precisa verificar se o token de cancelamento está sendo definido, salvar corretamente seu estado e sair do método RunAsync.

Lista de ações de testabilidade

Ação Descrição API gerenciada Cmdlet do PowerShell Faltas graciosas/desgraçadas
CleanTestState Remove todo o estado de teste do cluster em caso de desligamento incorreto do driver de teste. CleanTestStateAsync Remove-ServiceFabricTestState Não aplicável
InvokeDataLoss Induz a perda de dados em uma partição de serviço. InvokeDataLossAsync Invoke-ServiceFabricPartitionDataLoss Gracioso
InvoqueQuorumLoss Coloca uma determinada partição de serviço com estado em perda de quórum. InvokeQuorumLossAsync Invoke-ServiceFabricQuorumLoss Gracioso
MovePrimary Move a réplica primária especificada de um serviço com monitoração de estado para o nó de cluster especificado. MovePrimaryAsync Move-ServiceFabricPrimaryReplica Gracioso
MoveSecondary Move a réplica secundária atual de um serviço com monitoração de 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
RemoveReplica Simula uma falha de réplica removendo uma réplica de um cluster. Isso fechará a réplica e a fará a transição para a função 'Nenhuma', removendo todo o seu estado do cluster. RemoveReplicaAsync Remove-ServiceFabricReplica Gracioso
RestartDeployedCodePackage Simula uma falha de processo de pacote de código reiniciando um pacote de código implantado em um nó em um cluster. Isso anula o processo do pacote de código, que reiniciará todas as réplicas de serviço do usuário hospedadas nesse processo. RestartDeployedCodePackageAsync Restart-ServiceFabricDeployedCodePackage Ingrato
RestartNode Simula uma falha de nó de cluster do Service Fabric reiniciando um nó. RestartNodeAsync Restart-ServiceFabricNode Ingrato
RestartPartition Simula um cenário de apagão de datacenter ou de bloqueio de cluster reiniciando algumas ou todas as réplicas de uma partição. RestartPartitionAsync Restart-ServiceFabricPartition Gracioso
RestartReplica Simula uma falha de réplica reiniciando uma réplica persistente em um cluster, fechando a réplica e reabrindo-a. RestartReplicaAsync Restart-ServiceFabricReplica Gracioso
StartNode Inicia um nó em um cluster que já está parado. StartNodeAsync Start-ServiceFabricNode Não aplicável
StopNode Simula uma falha de nó parando um nó em um cluster. O nó permanecerá inativo até que o StartNode seja chamado. StopNodeAsync Stop-ServiceFabricNode Ingrato
ValidateApplication Valida a disponibilidade e a integridade de todos os serviços do Service Fabric em um aplicativo, geralmente depois de induzir alguma falha no sistema. ValidateApplicationAsync Test-ServiceFabricApplication Não aplicável
ValidateService Valida a disponibilidade e a integridade de um serviço do Service Fabric, geralmente depois de induzir alguma falha no sistema. ValidateServiceAsync Test-ServiceFabricService Não aplicável

Executando uma ação de capacidade de teste usando o PowerShell

Este tutorial mostra como executar uma ação de capacidade de teste usando o PowerShell. Você aprenderá como executar uma ação de capacidade de teste em um cluster local (caixa única) ou em um cluster do Azure. Microsoft.Fabric.Powershell.dll--o módulo PowerShell do Service Fabric--é instalado automaticamente quando você instala o MSI do Microsoft Service Fabric. O módulo é carregado automaticamente quando você abre um prompt do PowerShell.

Segmentos tutoriais:

Executar uma ação em um cluster de caixa única

Para executar uma ação de capacidade de teste em um cluster local, primeiro conecte-se ao cluster e abra o prompt 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á sendo executada em um nó chamado "Node1". O modo de conclusão especifica que ele não deve verificar se a ação do nó de reinicialização realmente foi bem-sucedida. Especificar o modo de conclusão como "Verificar" fará com que ele verifique se a ação de reinicialização realmente foi bem-sucedida. Em vez de especificar diretamente o nó pelo nome, você pode especificá-lo por meio de uma chave de partição e do tipo de réplica, da seguinte maneira:

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 usado para reiniciar um nó do Service Fabric em um cluster. Isso interromperá o processo de Fabric.exe, que reiniciará todas as réplicas de serviço do sistema e de serviço do usuário hospedadas nesse nó. Usar essa API para testar seu serviço ajuda a descobrir bugs ao longo dos caminhos de recuperação de failover. Ele ajuda a simular falhas de nó no cluster.

A captura de tela a seguir mostra o comando de testability Restart-ServiceFabricNode em ação.

Captura de tela da execução do comando Restart-ServiceFabricNode no PowerShell.

A saída 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. Depois que a ação de testabilidade (cmdlet) Restart-ServiceFabricNode é executada no nó, chamado Node.4, vemos que o tempo de atividade do nó foi redefinido.

Executar uma ação em um cluster do Azure

Executar uma ação de capacidade de teste (usando o PowerShell) em um cluster do Azure é semelhante a executar a ação em um cluster local. A única diferença é que, antes de executar a ação, em vez de se conectar ao cluster local, você precisa se conectar primeiro ao cluster do Azure.

Executando uma ação de testabilidade usando C#

Para executar uma ação de capacidade de teste usando C#, primeiro você precisa se conectar ao cluster usando FabricClient. Em seguida, obtenha os parâmetros necessários para executar a ação. Parâmetros diferentes podem ser usados para executar a mesma ação. Observando a ação RestartServiceFabricNode, uma maneira de executá-la é usando as 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 reinicialização realmente foi bem-sucedida. Especificar o modo de conclusão como "Verificar" fará com que ele verifique se a ação de reinicialização realmente foi bem-sucedida.
  • OperationTimeout define a quantidade de tempo para a operação ser concluída antes que uma exceção TimeoutException seja lançada.
  • CancellationToken permite que uma chamada pendente seja cancelada.

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

Para obter mais informações, consulte 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 auxiliar exposto na capacidade de teste e é usado para selecionar uma partição específica na qual executar qualquer uma das ações de testabilidade. Ele pode ser usado para selecionar uma partição específica se o ID da partição for conhecido de antemão. Ou, você pode fornecer a chave de partição e a operação resolverá o ID da partição internamente. Você também tem a opção de selecionar uma partição aleatória.

Para usar esse auxiliar, crie o objeto PartitionSelector e selecione a partição usando um dos métodos Select*. Em seguida, passe o objeto PartitionSelector para a API que o exige. Se nenhuma opção for selecionada, o padrão será 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

O ReplicaSelector é um auxiliar exposto na capacidade de teste e é usado para ajudar a selecionar uma réplica na qual executar qualquer uma das ações de testabilidade. Ele pode ser usado para selecionar uma réplica específica se o ID da réplica for conhecido de antemão. Além disso, você tem a opção de selecionar uma réplica primária ou uma secundária aleatória. ReplicaSelector deriva de PartitionSelector, portanto, você precisa selecionar a réplica e a partição na qual deseja executar a operação de testabilidade.

Para usar esse auxiliar, crie um objeto ReplicaSelector e defina a maneira como deseja selecionar a réplica e a partição. Em seguida, você pode passá-lo para a API que o exige. Se nenhuma opção for selecionada, o padrão será 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);

Próximos passos