Udostępnij za pośrednictwem


Obsługa błędów w Durable Functions (Azure Functions)

Orkiestracje funkcji Durable Function są implementowane w kodzie i mogą korzystać z wbudowanych funkcji obsługi błędów języka programowania. Naprawdę nie ma żadnych nowych pojęć, które należy nauczyć się dodawać obsługę błędów i rekompensatę do aranżacji. Istnieje jednak kilka zachowań, o których należy pamiętać.

Uwaga

Wersja 4 modelu programowania Node.js dla Azure Functions jest ogólnie dostępna. Nowy model w wersji 4 został zaprojektowany z myślą o bardziej elastycznym i intuicyjnym środowisku dla deweloperów języka JavaScript i Języka TypeScript. Dowiedz się więcej o różnicach między wersjami 3 i v4 w przewodniku migracji.

W poniższych fragmentach kodu język JavaScript (PM4) oznacza model programowania w wersji 4— nowe środowisko.

Błędy w funkcjach działań

Każdy wyjątek zgłaszany w funkcji działania jest wywoływany z powrotem do funkcji orkiestratora i zgłaszany jako FunctionFailedException. Możesz napisać kod obsługi błędów i rekompensaty, który odpowiada Twoim potrzebom w funkcji orkiestratora.

Rozważmy na przykład następującą funkcję orkiestratora, która transferuje fundusze z jednego konta do innego:

[FunctionName("TransferFunds")]
public static async Task Run([OrchestrationTrigger] IDurableOrchestrationContext context)
{
    var transferDetails = context.GetInput<TransferOperation>();

    await context.CallActivityAsync("DebitAccount",
        new
        {
            Account = transferDetails.SourceAccount,
            Amount = transferDetails.Amount
        });

    try
    {
        await context.CallActivityAsync("CreditAccount",
            new
            {
                Account = transferDetails.DestinationAccount,
                Amount = transferDetails.Amount
            });
    }
    catch (Exception)
    {
        // Refund the source account.
        // Another try/catch could be used here based on the needs of the application.
        await context.CallActivityAsync("CreditAccount",
            new
            {
                Account = transferDetails.SourceAccount,
                Amount = transferDetails.Amount
            });
    }
}

Uwaga

Poprzednie przykłady języka C# dotyczą Durable Functions 2.x. W przypadku Durable Functions 1.x należy użyć DurableOrchestrationContext polecenia zamiast IDurableOrchestrationContext. Aby uzyskać więcej informacji na temat różnic między wersjami, zobacz artykuł dotyczący wersji Durable Functions.

Jeśli pierwsze wywołanie funkcji CreditAccount zakończy się niepowodzeniem, funkcja orkiestratora skompensuje środki z powrotem na konto źródłowe.

Automatyczne ponawianie próby po awarii

Podczas wywoływania funkcji działań lub funkcji orkiestracji podrzędnej można określić zasady automatycznego ponawiania. Poniższy przykład próbuje wywołać funkcję do trzech razy i czeka 5 sekund między poszczególnymi ponownymi próbami:

[FunctionName("TimerOrchestratorWithRetry")]
public static async Task Run([OrchestrationTrigger] IDurableOrchestrationContext context)
{
    var retryOptions = new RetryOptions(
        firstRetryInterval: TimeSpan.FromSeconds(5),
        maxNumberOfAttempts: 3);

    await context.CallActivityWithRetryAsync("FlakyFunction", retryOptions, null);

    // ...
}

Uwaga

Poprzednie przykłady języka C# dotyczą Durable Functions 2.x. W przypadku Durable Functions 1.x należy użyć DurableOrchestrationContext polecenia zamiast IDurableOrchestrationContext. Aby uzyskać więcej informacji na temat różnic między wersjami, zobacz artykuł dotyczący wersji Durable Functions.

Wywołanie funkcji działania w poprzednim przykładzie przyjmuje parametr konfigurowania zasad automatycznego ponawiania prób. Istnieje kilka opcji dostosowywania zasad automatycznego ponawiania prób:

  • Maksymalna liczba prób: maksymalna liczba prób. Jeśli ustawiono wartość 1, nie będzie ponawiania próby.
  • Interwał ponawiania prób: czas oczekiwania przed pierwszą próbą ponawiania próby.
  • Współczynnik wycofywania: współczynnik używany do określania współczynnika wzrostu wycofywania. Wartość domyślna to 1.
  • Maksymalny interwał ponawiania prób: maksymalny czas oczekiwania między próbami ponawiania próby.
  • Limit czasu ponawiania prób: maksymalna ilość czasu na ponawianie prób. Domyślne zachowanie polega na ponowieniu próby przez czas nieokreślony.

Niestandardowe programy obsługi ponawiania prób

W przypadku korzystania z platformy .NET lub Java możesz również zaimplementować programy obsługi ponawiania prób w kodzie. Jest to przydatne, gdy deklaratywne zasady ponawiania nie są wystarczająco wyraźne. W przypadku języków, które nie obsługują niestandardowych procedur obsługi ponawiania prób, nadal istnieje możliwość implementowania zasad ponawiania przy użyciu pętli, obsługi wyjątków i czasomierzy do wstrzykiwania opóźnień między ponownymi próbami.

RetryOptions retryOptions = new RetryOptions(
    firstRetryInterval: TimeSpan.FromSeconds(5),
    maxNumberOfAttempts: int.MaxValue)
    {
        Handle = exception =>
        {
            // True to handle and try again, false to not handle and throw.
            if (exception is TaskFailedException failure)
            {
                // Exceptions from TaskActivities are always this type. Inspect the
                // inner Exception to get more details.
            }

            return false;
        };
    }

await ctx.CallActivityWithRetryAsync("FlakeyActivity", retryOptions, null);

Limity czasu funkcji

Jeśli ukończenie wywołania funkcji w funkcji orkiestratora trwa zbyt długo. Właściwym sposobem, aby to zrobić dzisiaj, jest utworzenie trwałego czasomierza z selektorem zadań "any", jak w poniższym przykładzie:

[FunctionName("TimerOrchestrator")]
public static async Task<bool> Run([OrchestrationTrigger] IDurableOrchestrationContext context)
{
    TimeSpan timeout = TimeSpan.FromSeconds(30);
    DateTime deadline = context.CurrentUtcDateTime.Add(timeout);

    using (var cts = new CancellationTokenSource())
    {
        Task activityTask = context.CallActivityAsync("FlakyFunction");
        Task timeoutTask = context.CreateTimer(deadline, cts.Token);

        Task winner = await Task.WhenAny(activityTask, timeoutTask);
        if (winner == activityTask)
        {
            // success case
            cts.Cancel();
            return true;
        }
        else
        {
            // timeout case
            return false;
        }
    }
}

Uwaga

Poprzednie przykłady języka C# dotyczą Durable Functions 2.x. W przypadku Durable Functions 1.x należy użyć DurableOrchestrationContext polecenia zamiast IDurableOrchestrationContext. Aby uzyskać więcej informacji na temat różnic między wersjami, zobacz artykuł dotyczący wersji Durable Functions.

Uwaga

Ten mechanizm nie kończy wykonywania funkcji działania w toku. Zamiast tego wystarczy, że funkcja orkiestratora zignoruje wynik i przejdzie dalej. Aby uzyskać więcej informacji, zobacz dokumentację czasomierzy .

Nieobsługiwane wyjątki

Jeśli funkcja orkiestratora zakończy się niepowodzeniem z nieobsługiwanym wyjątkiem, szczegóły wyjątku zostaną zarejestrowane, a wystąpienie zakończy się stanem Failed .

Następne kroki