Testability 案例

雲端基礎結構之類的大型分散式系統本身並不可靠。 Azure Service Fabric 讓開發人員能夠撰寫可在不可靠的基礎結構上執行的服務。 為了撰寫高品質的服務,開發人員必須能夠產生這類不可靠的基礎結構,才能測試其服務的穩定性。

「錯誤分析服務」讓開發人員可以引發錯誤動作,藉此以失敗情況測試服務。 但鎖定式模擬錯誤就僅只於此了。 若要進一步測試,您可以在 Service Fabric 中使用測試案例:混亂測試和容錯移轉測試。 這些案例會以很長的時間在整個叢集上模擬連續的交錯錯誤,包括非失誤性和失誤性錯誤。 一旦設定測試的比率和錯誤類型後,即可開始透過 C# API 或 PowerShell 在叢集和您的服務中產生錯誤。

警告

ChaosTestScenario 已被更有彈性、以服務為基礎的混亂取代。 請參閱 控制的混亂 了解詳細資訊。

混亂測試

混亂案例會在整個 Service Fabric 叢集中產生錯誤。 此案例會壓縮錯誤,通常是將幾個月或幾年壓縮到幾小時。 交錯錯誤和高錯誤率的組合,可以找到會在其他情形下被遺漏的極端狀況。 這會使服務的程式碼品質大幅提升。

混亂測試中模擬的錯誤

  • 重新啟動節點
  • 重新啟動已部署的程式碼封裝
  • 移除複本
  • 重新啟動複本
  • 移動主要複本 (選擇性)
  • 移動次要複本 (選擇性)

混亂測試會在指定的一段時間中,多次執行反覆的錯誤和叢集驗證。 讓叢集穩定和驗證成功的所需時間也是可設定的。 當您在叢集驗證中發生一次失敗,案例就會失敗。

例如,請考慮將測試設為執行 1 小時,且最多 3 個並行錯誤。 測試會引發 3 個錯誤,然後驗證叢集的健康情況。 上一個步驟的測試會反覆進行,直到叢集變成狀況不佳,或經過了 1 小時為止。 如果任何反覆運算中的叢集變成狀況不佳,也就是在設定的時間內不穩定,則測試就會失敗並產生例外狀況。 此例外狀況表示發生了錯誤,且需要進一步調查。

以目前的形式來看,混亂測試的錯誤產生引擎只會引發安全的錯誤。 這表示因為沒有外部錯誤,所以永遠不會發生仲裁或資料遺失。

重要的組態選項

  • TimeToRun:測試在成功完成前的總執行時間。 測試可以提前完成,而不必等驗證失敗。
  • MaxClusterStabilizationTimeout:測試失敗前,等候叢集變成狀況良好的時間上限。 執行的檢查會查看叢集健康情況或服務健康情況是否正常、服務分割區是否達到目標複本的設定大小,以及是否沒有 InBuild 複本。
  • MaxConcurrentFaults:每個反覆運算中引發的最大並行錯誤數。 數量越大,測試會越積極,因此導致更複雜的容錯移轉和轉換組合。 無論此組態的數量多高,測試都能保證缺少外部錯誤時,就不會發生仲裁或資料遺失。
  • EnableMoveReplicaFaults:啟用或停用造成主要或次要複本移動的錯誤。 預設會停用這些錯誤。
  • WaitTimeBetweenIterations:反覆運算之間的等待時間長度,也就是在一輪的錯誤與對應的驗證後等待下一輪。

如何執行混亂測試

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

Service Fabric Powershell 模組包含兩種開始混沌案例的方式。 Invoke-ServiceFabricChaosTestScenario 是用戶端型,如果用戶端電腦在測試中途關機,不會引入進一步的錯誤。 或者,您也可以使用一組命令,在電腦關機時讓測試保持執行狀態。 Start-ServiceFabricChaos 會使用稱為 FaultAnalysisService 的具狀態和可靠系統服務,確保在 TimeToRun 運作之前仍然會引入錯誤。 Stop-ServiceFabricChaos 可以用來手動停止案例,Get-ServiceFabricChaosReport 會取得報告。 如需詳細資訊,請參閱 Azure Service Fabric Powershell 參考在 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

容錯移轉測試

容錯移轉測試案例是以特定服務分割區為目標的混亂測試案例版本。 此測試會測試容錯移轉對特定服務分割區的影響,且其他服務不會受到影響。 設定了目標分割區資訊和其他參數後,此測試會以用戶端工具的形式執行,並使用 C# API 或 Powershell 來產生服務分割區的錯誤。 案例會在您的商務邏輯執行時,反覆進行一連串模擬的錯誤及服務驗證,同時提供工作負載。 服務驗證中若有失敗,表示有需要進一步調查的問題。

在容錯移轉測試中模擬的錯誤

  • 重新啟動分割區所在的已部署程式碼封裝
  • 移除主要/次要複本或無狀態執行個體
  • 重新啟動主要的次要複本 (如果是保存的服務)
  • 移動主要複本
  • 移動次要複本
  • 重新啟動分割區

容錯移轉測試會引發選定的錯誤,然後在服務上執行驗證,以確保其穩定性。 容錯移轉測試一次只會引發一個錯誤,不像混亂測試中可能會有多個錯誤。 如果在每個錯誤後,服務分割區沒有在設定的逾時內變穩定,測試會失敗。 此測試只會引發安全的錯誤。 這表示因為沒有外部錯誤,所以不會發生仲裁或資料遺失。

重要的組態選項

  • PartitionSelector:指定需要做為目標分割區的選取器物件。
  • TimeToRun:測試在完成前的總執行時間。
  • MaxServiceStabilizationTimeout:測試失敗前,等候叢集變成狀況良好的時間上限。 執行的檢查會查看服務健康情況是否正常,或是所有分割區是否達到目標複本的設定大小,以及是否沒有 InBuild 複本。
  • WaitTimeBetweenFaults:每個錯誤和驗證的循環之間要等候的時間長度。

如何執行容錯移轉測試

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