Dela via


Hantera fel i Durable Functions (Azure Functions)

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

Anteckning

Version 4 av Node.js programmeringsmodell 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 felhanterings- och kompensationskod som passar dina behov i orchestrator-funktionen.

Tänk dig till exempel följande orkestreringsfunktion 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
            });
    }
}

Anteckning

Föregående C#-exempel ä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 olika 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);

    // ...
}

Anteckning

Föregående C#-exempel ä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 olika versioner finns i artikeln Durable Functions versioner.

Aktivitetsfunktionsanropet i föregående exempel använder 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 inga återfö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 ökningstakten 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 även implementera omfö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 att skapa en hållbar timer med en valfri aktivitetsvä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;
        }
    }
}

Anteckning

Föregående C#-exempel ä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 olika versioner finns i artikeln Durable Functions versioner.

Anteckning

Den här mekanismen avslutar inte pågående aktivitetsfunktionskörning. I stället tillåter det bara att orchestrator-funktionen ignorerar resultatet och går vidare. Mer information finns i timerdokumentationen .

Ohanterade undantag

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

Nästa steg