Udostępnij za pośrednictwem


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

Orkiestracje funkcji durable 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órych musisz nauczyć się dodawać do aranżacji obsługę błędów i rekompensatę. Istnieje jednak kilka zachowań, o których należy pamiętać.

Uwaga

Wersja 4 modelu programowania Node.js dla usługi 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ęzyków JavaScript i TypeScript. Dowiedz się więcej o różnicach między wersjami 3 i v4 w przewodniku migracji.

W poniższych fragmentach kodu 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 marshaling z powrotem do funkcji orkiestratora i zgłaszany jako FunctionFailedException. Możesz napisać kod obsługi błędów i kompensacji, który odpowiada Twoim potrzebom w funkcji orkiestratora.

Rozważmy na przykład następującą funkcję orkiestratora, która przekazuje 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ą rozszerzenia Durable Functions 2.x. W przypadku rozszerzenia Durable Functions 1.x należy użyć funkcji DurableOrchestrationContext IDurableOrchestrationContextzamiast . Aby uzyskać więcej informacji na temat różnic między wersjami, zobacz artykuł Wersje rozszerzenia Durable Functions.

Jeśli pierwsze wywołanie funkcji CreditAccount zakończy się niepowodzeniem, funkcja orkiestratora kompensuje środki z powrotem do konta źródłowego.

Automatyczne ponawianie próby po awarii

Podczas wywoływania funkcji działań lub funkcji aranżacji podrzędnej można określić zasady automatycznego ponawiania. Poniższy przykład próbuje wywołać funkcję maksymalnie trzy razy i czeka 5 sekund między kolejnymi 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ą rozszerzenia Durable Functions 2.x. W przypadku rozszerzenia Durable Functions 1.x należy użyć funkcji DurableOrchestrationContext IDurableOrchestrationContextzamiast . Aby uzyskać więcej informacji na temat różnic między wersjami, zobacz artykuł Wersje rozszerzenia Durable Functions.

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

  • Maksymalna liczba prób: maksymalna liczba prób. Jeśli zostanie ustawiona 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 ponownymi próbami.
  • Limit czasu ponawiania prób: maksymalna ilość czasu na ponawianie prób. Domyślne zachowanie polega na ponawianiu próby przez czas nieokreślony.

Niestandardowe programy obsługi ponawiania prób

W przypadku korzystania z platformy .NET lub Języka Java możesz również zaimplementować programy obsługi ponawiania prób w kodzie. Jest to przydatne, gdy zasady ponawiania deklaratywnego nie są wystarczająco wyraziste. 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 w celu 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 działania funkcji trwa zbyt długo, możesz porzucić wywołanie funkcji w funkcji orkiestratora. 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ą rozszerzenia Durable Functions 2.x. W przypadku rozszerzenia Durable Functions 1.x należy użyć funkcji DurableOrchestrationContext IDurableOrchestrationContextzamiast . Aby uzyskać więcej informacji na temat różnic między wersjami, zobacz artykuł Wersje rozszerzenia Durable Functions.

Uwaga

Ten mechanizm nie kończy wykonywania funkcji działania w toku. Zamiast tego po prostu umożliwia funkcji orkiestrator ignorowanie wyniku i przechodzenie 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 są rejestrowane, a wystąpienie kończy się stanem Failed .

Następne kroki