Dela via


Hantera fel i Durable Functions (Azure Functions)

Durable Function-orkestreringar implementeras i kod och kan använda programmeringsspråkets inbyggda funktioner för felhantering. Det finns egentligen inga nya begrepp som du behöver lära dig att lägga till felhantering och kompensation i orkestreringarna. Det finns dock några beteenden som du bör känna till.

Kommentar

Version 4 av Node.js programmeringsmodellen för Azure Functions är allmänt tillgänglig. Den nya v4-modellen är utformad för att ha en mer flexibel och intuitiv upplevelse för JavaScript- och TypeScript-utvecklare. Läs mer om skillnaderna mellan v3 och v4 i migreringsguiden.

I följande kodfragment anger JavaScript (PM4) programmeringsmodellen V4, den nya upplevelsen.

Fel i aktivitetsfunktioner

Alla undantag som genereras i en aktivitetsfunktion konverteras tillbaka till orchestrator-funktionen och genereras som en FunctionFailedException. Du kan skriva felhantering och kompensationskod som passar dina behov i orchestrator-funktionen.

Tänk dig till exempel följande orchestrator-funktion som överför medel från ett konto till ett annat:

[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
            });
    }
}

Kommentar

De tidigare C#-exemplen är för Durable Functions 2.x. För Durable Functions 1.x måste du använda DurableOrchestrationContext i stället för IDurableOrchestrationContext. Mer information om skillnaderna mellan versioner finns i artikeln Durable Functions-versioner .

Om det första CreditAccount-funktionsanropet misslyckas kompenserar orkestreringsfunktionen genom att kreditera pengarna tillbaka till källkontot.

Automatiskt återförsök vid fel

När du anropar aktivitetsfunktioner eller underorkestreringsfunktioner kan du ange en princip för automatiskt återförsök. Följande exempel försöker anropa en funktion upp till tre gånger och väntar 5 sekunder mellan varje nytt försök:

[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);

    // ...
}

Kommentar

De tidigare C#-exemplen är för Durable Functions 2.x. För Durable Functions 1.x måste du använda DurableOrchestrationContext i stället för IDurableOrchestrationContext. Mer information om skillnaderna mellan versioner finns i artikeln Durable Functions-versioner .

Aktivitetsfunktionsanropet i föregående exempel tar en parameter för att konfigurera en automatisk återförsöksprincip. Det finns flera alternativ för att anpassa principen för automatiskt återförsök:

  • Maximalt antal försök: Det maximala antalet försök. Om värdet är 1 görs inget nytt försök.
  • Första återförsöksintervallet: Hur lång tid det tar att vänta innan det första återförsöket.
  • Backoff-koefficient: Den koefficient som används för att fastställa ökningshastigheten för backoff. Standardvärdet är 1.
  • Maximalt återförsöksintervall: Den maximala väntetiden mellan återförsök.
  • Tidsgräns för återförsök: Den maximala tid som du behöver ägna åt att göra återförsök. Standardbeteendet är att försöka igen på obestämd tid.

Anpassade återförsökshanterare

När du använder .NET eller Java kan du också implementera återförsökshanterare i kod. Detta är användbart när deklarativa återförsöksprinciper inte är tillräckligt uttrycksfulla. För språk som inte stöder anpassade återförsökshanterare har du fortfarande möjlighet att implementera återförsöksprinciper med hjälp av loopar, undantagshantering och timers för att mata in fördröjningar mellan återförsök.

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);

Funktionstimeouter

Du kanske vill avbryta ett funktionsanrop i en orkestreringsfunktion om det tar för lång tid att slutföra. Det rätta sättet att göra detta i dag är genom att skapa en varaktig timer med en "valfri" uppgiftsväljare, som i följande exempel:

[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;
        }
    }
}

Kommentar

De tidigare C#-exemplen är för Durable Functions 2.x. För Durable Functions 1.x måste du använda DurableOrchestrationContext i stället för IDurableOrchestrationContext. Mer information om skillnaderna mellan versioner finns i artikeln Durable Functions-versioner .

Kommentar

Den här mekanismen avslutar inte funktionskörningen under pågående aktivitet. I stället tillåter den helt enkelt orkestreringsfunktionen att ignorera resultatet och gå vidare. Mer information finns i dokumentationen om Timers .

Ohanterade undantag

Om en orchestrator-funktion misslyckas med ett ohanterat undantag loggas information om undantaget och instansen slutförs med status Failed .

Nästa steg