Scenariusze testowania

Duże systemy rozproszone, takie jak infrastruktura chmury, są z natury zawodne. Usługa Azure Service Fabric umożliwia deweloperom pisanie usług do uruchamiania na podstawie zawodnych infrastruktur. Aby napisać wysokiej jakości usługi, deweloperzy muszą mieć możliwość wywołania takiej zawodnej infrastruktury w celu przetestowania stabilności swoich usług.

Usługa Analizy błędów umożliwia deweloperom wywoływanie akcji błędów w celu testowania usług w obecności awarii. Jednak ukierunkowane symulowane błędy będą dostępne tylko do tej pory. Aby kontynuować testowanie, możesz użyć scenariuszy testowych w usłudze Service Fabric: test chaosu i test trybu failover. Te scenariusze symulują ciągłe przeplatane błędy, zarówno bezproblemowe, jak i niegrzeczne, w całym klastrze przez dłuższy czas. Po skonfigurowaniu testu z szybkością i rodzajem błędów można go uruchomić za pośrednictwem interfejsów API języka C# lub programu PowerShell, aby wygenerować błędy w klastrze i usłudze.

Ostrzeżenie

ChaosTestScenario jest zastępowany bardziej odpornym chaosem opartym na usługach. Aby uzyskać więcej informacji, zapoznaj się z nowym artykułem Kontrolowany chaos .

Test chaosu

Scenariusz chaosu generuje błędy w całym klastrze usługi Service Fabric. Scenariusz kompresuje błędy zwykle widoczne w miesiącach lub latach do kilku godzin. Połączenie przeplatanych błędów z wysokim współczynnikiem błędów znajduje przypadki narożne, które w przeciwnym razie zostały pominięte. Prowadzi to do znacznej poprawy jakości kodu usługi.

Błędy symulowane w teście chaosu

  • Ponowne uruchamianie węzła
  • Ponowne uruchamianie wdrożonego pakietu kodu
  • Usuwanie repliki
  • Ponowne uruchamianie repliki
  • Przenoszenie repliki podstawowej (opcjonalnie)
  • Przenoszenie repliki pomocniczej (opcjonalnie)

Test chaosu uruchamia wiele iteracji błędów i walidacji klastra przez określony okres czasu. Można również skonfigurować czas spędzony na stabilizacji klastra i pomyślne sprawdzenie poprawności. Scenariusz kończy się niepowodzeniem po osiągnięciu pojedynczego błędu w weryfikacji klastra.

Rozważmy na przykład uruchomienie zestawu testowego przez jedną godzinę z maksymalnie trzema współbieżnymi błędami. Test wywoła trzy błędy, a następnie zweryfikuje kondycję klastra. Test będzie iterować przez poprzedni krok, aż klaster stanie się w złej kondycji lub jedna godzina zakończy się pomyślnie. Jeśli klaster stanie się w złej kondycji w jakiejkolwiek iteracji, tj. nie stabilizuje się w skonfigurowanym czasie, test zakończy się niepowodzeniem z wyjątkiem. Ten wyjątek wskazuje, że coś poszło nie tak i wymaga dalszych badań.

W obecnej formie aparat generowania błędów w teście chaosu wywołuje tylko bezpieczne błędy. Oznacza to, że w przypadku braku błędów zewnętrznych kworum lub utraty danych nigdy nie wystąpią.

Ważne opcje konfiguracji

  • TimeToRun: łączny czas uruchomienia testu przed zakończeniem z powodzeniem. Test może zakończyć się wcześniej zamiast niepowodzenia walidacji.
  • MaxClusterStabilizationTimeout: maksymalny czas oczekiwania na kondycję klastra przed niepowodzeniem testu. Sprawdzane są, czy kondycja klastra jest OK, kondycja usługi jest OK, docelowy rozmiar zestawu replik jest osiągany dla partycji usługi i nie istnieją repliki InBuild.
  • MaxConcurrentFaults: maksymalna liczba współbieżnych błędów wywołanych w każdej iteracji. Im większa liczba, tym bardziej agresywny test, w związku z tym powoduje bardziej złożone przejścia w tryb failover i kombinacje przejścia. Test gwarantuje, że w przypadku braku błędów zewnętrznych nie będzie kworum lub utraty danych, niezależnie od tego, jak wysoka jest ta konfiguracja.
  • EnableMoveReplicaFaults: włącza lub wyłącza błędy powodujące przenoszenie replik podstawowych lub pomocniczych. Te błędy są domyślnie wyłączone.
  • WaitTimeBetweenIterations: czas oczekiwania między iteracjami, tj. po rundzie błędów i odpowiedniej weryfikacji.

Jak uruchomić test chaosu

Przykład w języku C#

using System;
using System.Fabric;
using System.Fabric.Testability.Scenario;
using System.Threading;
using System.Threading.Tasks;

class Test
{
    public static int Main(string[] args)
    {
        string clusterConnection = "localhost:19000";

        Console.WriteLine("Starting Chaos Test Scenario...");
        try
        {
            RunChaosTestScenarioAsync(clusterConnection).Wait();
        }
        catch (AggregateException ae)
        {
            Console.WriteLine("Chaos Test Scenario did not complete: ");
            foreach (Exception ex in ae.InnerExceptions)
            {
                if (ex is FabricException)
                {
                    Console.WriteLine("HResult: {0} Message: {1}", ex.HResult, ex.Message);
                }
            }
            return -1;
        }

        Console.WriteLine("Chaos Test Scenario completed.");
        return 0;
    }

    static async Task RunChaosTestScenarioAsync(string clusterConnection)
    {
        TimeSpan maxClusterStabilizationTimeout = TimeSpan.FromSeconds(180);
        uint maxConcurrentFaults = 3;
        bool enableMoveReplicaFaults = true;

        // Create FabricClient with connection and security information here.
        FabricClient fabricClient = new FabricClient(clusterConnection);

        // The chaos test scenario should run at least 60 minutes or until it fails.
        TimeSpan timeToRun = TimeSpan.FromMinutes(60);
        ChaosTestScenarioParameters scenarioParameters = new ChaosTestScenarioParameters(
          maxClusterStabilizationTimeout,
          maxConcurrentFaults,
          enableMoveReplicaFaults,
          timeToRun);

        // Other related parameters:
        // Pause between two iterations for a random duration bound by this value.
        // scenarioParameters.WaitTimeBetweenIterations = TimeSpan.FromSeconds(30);
        // Pause between concurrent actions for a random duration bound by this value.
        // scenarioParameters.WaitTimeBetweenFaults = TimeSpan.FromSeconds(10);

        // Create the scenario class and execute it asynchronously.
        ChaosTestScenario chaosScenario = new ChaosTestScenario(fabricClient, scenarioParameters);

        try
        {
            await chaosScenario.ExecuteAsync(CancellationToken.None);
        }
        catch (AggregateException ae)
        {
            throw ae.InnerException;
        }
    }
}

PowerShell

Moduł programu PowerShell usługi Service Fabric zawiera dwa sposoby rozpoczęcia scenariusza chaosu. Invoke-ServiceFabricChaosTestScenario jest oparta na kliencie, a jeśli maszyna kliencka zostanie zamknięta w połowie testu, nie zostaną wprowadzone żadne dalsze błędy. Alternatywnie istnieje zestaw poleceń przeznaczonych do utrzymania testu uruchomionego w przypadku zamknięcia maszyny. Start-ServiceFabricChaos używa stanowej i niezawodnej usługi systemowej o nazwie FaultAnalysisService, zapewniając, że błędy pozostaną wprowadzone do momentu uruchomienia funkcji TimeToRun. Stop-ServiceFabricChaos może służyć do ręcznego zatrzymywania scenariusza i Get-ServiceFabricChaosReport uzyskiwania raportu. Aby uzyskać więcej informacji , zobacz dokumentację programu PowerShell usługi Azure Service Fabric i inducing kontrolowanych chaosów w klastrach usługi Service Fabric.

$connection = "localhost:19000"
$timeToRun = 60
$maxStabilizationTimeSecs = 180
$concurrentFaults = 3
$waitTimeBetweenIterationsSec = 60

Connect-ServiceFabricCluster $connection

Invoke-ServiceFabricChaosTestScenario -TimeToRunMinute $timeToRun -MaxClusterStabilizationTimeoutSec $maxStabilizationTimeSecs -MaxConcurrentFaults $concurrentFaults -EnableMoveReplicaFaults -WaitTimeBetweenIterationsSec $waitTimeBetweenIterationsSec

Test trybu failover

Scenariusz testu trybu failover to wersja scenariusza testu chaosu, która jest przeznaczona dla określonej partycji usługi. Testuje ona wpływ przejścia w tryb failover na określoną partycję usługi, pozostawiając inne usługi bez wpływu. Po skonfigurowaniu informacji o partycji docelowej i innych parametrach jest ono uruchamiane jako narzędzie po stronie klienta, które używa interfejsów API języka C# lub programu PowerShell do generowania błędów dla partycji usługi. Scenariusz wykonuje iterację po sekwencji symulowanych błędów i weryfikacji usługi, podczas gdy logika biznesowa działa po stronie, aby zapewnić obciążenie. Niepowodzenie weryfikacji usługi wskazuje problem, który wymaga dalszego zbadania.

Błędy symulowane w teście trybu failover

  • Uruchom ponownie wdrożony pakiet kodu, w którym jest hostowana partycja
  • Usuwanie repliki podstawowej/pomocniczej lub wystąpienia bezstanowego
  • Uruchom ponownie podstawową replikę pomocniczą (jeśli utrwalone usługi)
  • Przenoszenie repliki podstawowej
  • Przenoszenie repliki pomocniczej
  • Uruchom ponownie partycję

Test trybu failover wywołuje wybraną usterkę, a następnie uruchamia walidację w usłudze, aby zapewnić jej stabilność. Test trybu failover wywołuje tylko jedną usterkę w danym momencie, w przeciwieństwie do możliwych wielu błędów w teście chaosu. Jeśli partycja usługi nie ustabilizuje się w ramach skonfigurowanego limitu czasu po każdym błędzie, test zakończy się niepowodzeniem. Test wywołuje tylko bezpieczne błędy. Oznacza to, że w przypadku braku awarii zewnętrznych nie wystąpi kworum lub utrata danych.

Ważne opcje konfiguracji

  • PartitionSelector: obiekt selektora określający partycję, która musi być docelowa.
  • TimeToRun: łączny czas uruchomienia testu przed zakończeniem.
  • MaxServiceStabilizationTimeout: maksymalny czas oczekiwania na kondycję klastra przed niepowodzeniem testu. Sprawdzane są, czy kondycja usługi jest OK, docelowy rozmiar zestawu replik jest osiągany dla wszystkich partycji i nie istnieją repliki InBuild.
  • WaitTimeBetweenFaults: czas oczekiwania między każdym cyklem awarii a weryfikacją.

Jak uruchomić test trybu failover

C#

using System;
using System.Fabric;
using System.Fabric.Testability.Scenario;
using System.Threading;
using System.Threading.Tasks;

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

        Console.WriteLine("Starting Chaos Test Scenario...");
        try
        {
            RunFailoverTestScenarioAsync(clusterConnection, serviceName).Wait();
        }
        catch (AggregateException ae)
        {
            Console.WriteLine("Chaos Test Scenario did not complete: ");
            foreach (Exception ex in ae.InnerExceptions)
            {
                if (ex is FabricException)
                {
                    Console.WriteLine("HResult: {0} Message: {1}", ex.HResult, ex.Message);
                }
            }
            return -1;
        }

        Console.WriteLine("Chaos Test Scenario completed.");
        return 0;
    }

    static async Task RunFailoverTestScenarioAsync(string clusterConnection, Uri serviceName)
    {
        TimeSpan maxServiceStabilizationTimeout = TimeSpan.FromSeconds(180);
        PartitionSelector randomPartitionSelector = PartitionSelector.RandomOf(serviceName);

        // Create FabricClient with connection and security information here.
        FabricClient fabricClient = new FabricClient(clusterConnection);

        // The chaos test scenario should run at least 60 minutes or until it fails.
        TimeSpan timeToRun = TimeSpan.FromMinutes(60);
        FailoverTestScenarioParameters scenarioParameters = new FailoverTestScenarioParameters(
          randomPartitionSelector,
          timeToRun,
          maxServiceStabilizationTimeout);

        // Other related parameters:
        // Pause between two iterations for a random duration bound by this value.
        // scenarioParameters.WaitTimeBetweenIterations = TimeSpan.FromSeconds(30);
        // Pause between concurrent actions for a random duration bound by this value.
        // scenarioParameters.WaitTimeBetweenFaults = TimeSpan.FromSeconds(10);

        // Create the scenario class and execute it asynchronously.
        FailoverTestScenario failoverScenario = new FailoverTestScenario(fabricClient, scenarioParameters);

        try
        {
            await failoverScenario.ExecuteAsync(CancellationToken.None);
        }
        catch (AggregateException ae)
        {
            throw ae.InnerException;
        }
    }
}

PowerShell

$connection = "localhost:19000"
$timeToRun = 60
$maxStabilizationTimeSecs = 180
$waitTimeBetweenFaultsSec = 10
$serviceName = "fabric:/SampleApp/SampleService"

Connect-ServiceFabricCluster $connection

Invoke-ServiceFabricFailoverTestScenario -TimeToRunMinute $timeToRun -MaxServiceStabilizationTimeoutSec $maxStabilizationTimeSecs -WaitTimeBetweenFaultsSec $waitTimeBetweenFaultsSec -ServiceName $serviceName -PartitionKindSingleton