Azure Functions – felhantering och återförsök

Det är viktigt att hantera fel i Azure Functions för att undvika förlorade data, undvika missade händelser och övervaka programmets hälsotillstånd. Det är också ett viktigt sätt att hjälpa dig att förstå återförsöksbeteenden för händelsebaserade utlösare.

I den här artikeln beskrivs allmänna strategier för felhantering och tillgängliga återförsöksstrategier.

Viktigt!

Principstöd för omprövning av förhandsversioner för vissa utlösare togs bort i december 2022. Återförsöksprinciper för utlösare som stöds är nu allmänt tillgängliga (GA). En lista över tillägg som för närvarande stöder återförsöksprinciper finns i avsnittet Återförsök .

Hantera fel

Fel som uppstår i en Azure-funktion kan komma från:

  • Användning av inbyggda Functions-utlösare och bindningar.
  • Anrop till API:er för underliggande Azure-tjänster.
  • Anrop till REST-slutpunkter.
  • Anrop till klientbibliotek, paket eller API:er från tredje part.

För att undvika dataförlust eller missade meddelanden är det viktigt att öva på god felhantering. I den här tabellen beskrivs några rekommenderade metoder för felhantering och länkar till mer information.

Rekommendation Details
Aktivera Application Insights Azure Functions integreras med Application Insights för att samla in feldata, prestandadata och körningsloggar. Du bör använda Application Insights för att identifiera och bättre förstå fel som inträffar i dina funktionskörningar. Mer information finns i Övervaka Azure Functions.
Använda strukturerad felhantering Det är viktigt att samla in och logga fel för att övervaka programmets hälsa. Den översta nivån av någon funktionskod bör innehålla ett try/catch-block. I catch-blocket kan du samla in och logga fel. Information om vilka fel som kan uppstå av bindningar finns i Bindningsfelkoder. Beroende på din specifika strategi för återförsök kan du också skapa ett nytt undantag för att köra funktionen igen.
Planera din strategi för återförsök Flera Functions-bindningstillägg ger inbyggt stöd för återförsök och andra låter dig definiera återförsöksprinciper som implementeras av Functions-körningen. För utlösare som inte tillhandahåller återförsöksbeteenden bör du överväga att implementera ditt eget återförsöksschema. Mer information finns i Försök igen.
Design för idempotens Förekomsten av fel när du bearbetar data kan vara ett problem för dina funktioner, särskilt när du bearbetar meddelanden. Det är viktigt att tänka på vad som händer när felet inträffar och hur du undviker duplicerad bearbetning. Mer information finns i Designa Azure Functions för identiska indata.

Försök

Det finns två typer av återförsök tillgängliga för dina funktioner:

  • Inbyggda återförsöksbeteenden för enskilda utlösartillägg
  • Återförsöksprinciper som tillhandahålls av Functions-körningen

Följande tabell anger vilka utlösare som stöder återförsök och var återförsöksbeteendet har konfigurerats. Den länkar också till mer information om fel som kommer från de underliggande tjänsterna.

Utlösare/bindning Försök att hämta källan igen Konfiguration
Azure Cosmos DB Återförsöksprinciper Funktionsnivå
Blob Storage Bindningstillägg host.json
Event Grid Bindningstillägg Händelseprenumeration
Event Hubs Återförsöksprinciper Funktionsnivå
Kafka Återförsöksprinciper Funktionsnivå
Queue Storage Bindningstillägg host.json
RabbitMQ Bindningstillägg Kö för obeställbara meddelanden
Service Bus Bindningstillägg host.json*
Timer Återförsöksprinciper Funktionsnivå

*Kräver version 5.x av Azure Service Bus-tillägget. I äldre tilläggsversioner implementeras återförsöksbeteenden av Service Bus-kön för obeställbara meddelanden.

Principer för nya försök

Med Azure Functions kan du definiera återförsöksprinciper för specifika utlösartyper som framtvingas av körningen. Dessa utlösartyper stöder för närvarande återförsöksprinciper:

Återförsöksstöd är detsamma för python-programmeringsmodellerna v1 och v2.

Återförsöksprinciper stöds inte i version 1.x av Functions-körningen.

Återförsöksprincipen instruerar körningen att köra en misslyckad körning igen tills antingen slutförandet har slutförts eller det maximala antalet återförsök har nåtts.

En återförsöksprincip utvärderas när en funktion som körs av en utlösartyp som stöds genererar ett ohanterat undantag. Som bästa praxis bör du fånga alla undantag i koden och skapa nya undantag för eventuella fel som du vill resultera i ett nytt försök.

Viktigt!

Kontrollpunkter för Event Hubs skrivs inte förrän återförsöksprincipen för körningen har slutförts. På grund av det här beteendet pausas förloppet för den specifika partitionen tills den aktuella batchen har bearbetats.

Version 5.x av Event Hubs-tillägget stöder ytterligare återförsöksfunktioner för interaktioner mellan Functions-värden och händelsehubben. Mer information clientRetryOptions finns i referensen för Event Hubs host.json.

Återförsöksstrategier

Du kan konfigurera två återförsöksstrategier som stöds av principen:

En angiven tidsperiod tillåts förflutit mellan varje nytt försök.

När du kör i en förbrukningsplan debiteras du bara för den tid som funktionskoden körs. Du debiteras inte för väntetiden mellan körningarna i någon av dessa återförsöksstrategier.

Maximalt antal återförsök

Du kan konfigurera det maximala antalet gånger som en funktionskörning görs om innan ett eventuellt fel uppstår. Det aktuella antalet återförsök lagras i instansens minne.

Det är möjligt att en instans får ett fel mellan återförsök. När en instans misslyckas under en återförsöksprincip går antalet återförsök förlorade. När det uppstår instansfel kan Event Hubs-utlösaren återuppta bearbetningen och försöka utföra batchen igen på en ny instans, med återförsöksantalet återställt till noll. Timerutlösaren återupptas inte på en ny instans.

Det här beteendet innebär att det maximala antalet återförsök är ett bra försök. I vissa sällsynta fall kan en körning göras om mer än det begärda maximala antalet gånger. För Timer-utlösare kan återförsöken vara mindre än det maximala antal som begärs.

Återförsöksexempel

Exempel finns för strategier för både fast fördröjning och exponentiell backoff. Om du vill se exempel för en specifik strategi måste du först välja den strategin på föregående flik.

Återförsök på funktionsnivå stöds med följande NuGet-paket:

[Function(nameof(TimerFunction))]
[FixedDelayRetry(5, "00:00:10")]
public static void Run([TimerTrigger("0 */5 * * * *")] TimerInfo timerInfo,
    FunctionContext context)
{
    var logger = context.GetLogger(nameof(TimerFunction));
    logger.LogInformation($"Function Ran. Next timer schedule = {timerInfo.ScheduleStatus.Next}");
}
Property beskrivning
MaxRetryCount Obligatoriskt. Det maximala antalet återförsök som tillåts per funktionskörning. -1 innebär att försöka igen på obestämd tid.
DelayInterval Fördröjningen som används mellan återförsök. Ange den som en sträng med formatet HH:mm:ss.

Här är ett exempel på en återförsöksprincip som definierats i filen function.json :

{
    "disabled": false,
    "bindings": [
        {
            ....
        }
    ],
    "retry": {
        "strategy": "fixedDelay",
        "maxRetryCount": 4,
        "delayInterval": "00:00:10"
    }
}

Du kan ange dessa egenskaper för principdefinitioner för återförsök:

Property beskrivning
Strategi Obligatoriskt. Återförsöksstrategin som ska användas. Giltig värden är fixedDelay och exponentialBackoff.
maxRetryCount Obligatoriskt. Det maximala antalet återförsök som tillåts per funktionskörning. -1 innebär att försöka igen på obestämd tid.
delayInterval Fördröjningen som används mellan återförsök när du använder en fixedDelay strategi. Ange den som en sträng med formatet HH:mm:ss.
minimumInterval Minsta fördröjning vid återförsök när du använder en exponentialBackoff strategi. Ange den som en sträng med formatet HH:mm:ss.
maximumInterval Den maximala fördröjningen för återförsök när du använder exponentialBackoff en strategi. Ange den som en sträng med formatet HH:mm:ss.

Hur du definierar återförsöksprincipen för utlösaren beror på din Node.js version.

Här är ett exempel på en Timer-utlösarfunktion som använder en strategi för återförsök med fast fördröjning:

const { app } = require('@azure/functions');

app.timer('timerTriggerWithRetry', {
    schedule: '0 */5 * * * *',
    retry: {
        strategy: 'fixedDelay',
        delayInterval: {
            seconds: 10,
        },
        maxRetryCount: 4,
    },
    handler: (myTimer, context) => {
        if (context.retryContext?.retryCount < 2) {
            throw new Error('Retry!');
        } else {
            context.log('Timer function processed request.');
        }
    },
});

Hur du definierar återförsöksprincipen för utlösaren beror på din Node.js version.

Här är ett exempel på en Timer-utlösarfunktion som använder en strategi för återförsök med fast fördröjning:

import { app, InvocationContext, Timer } from '@azure/functions';

export async function timerTriggerWithRetry(myTimer: Timer, context: InvocationContext): Promise<void> {
    if (context.retryContext?.retryCount < 2) {
        throw new Error('Retry!');
    } else {
        context.log('Timer function processed request.');
    }
}

app.timer('timerTriggerWithRetry', {
    schedule: '0 */5 * * * *',
    retry: {
        strategy: 'fixedDelay',
        delayInterval: {
            seconds: 10,
        },
        maxRetryCount: 4,
    },
    handler: timerTriggerWithRetry,
});

Du kan ange dessa egenskaper för principdefinitioner för återförsök:

Property beskrivning
Strategi Obligatoriskt. Återförsöksstrategin som ska användas. Giltig värden är fixedDelay och exponentialBackoff.
maxRetryCount Obligatoriskt. Det maximala antalet återförsök som tillåts per funktionskörning. -1 innebär att försöka igen på obestämd tid.
delayInterval Fördröjningen som används mellan återförsök när du använder en fixedDelay strategi. Ange den som en sträng med formatet HH:mm:ss.
minimumInterval Minsta fördröjning vid återförsök när du använder en exponentialBackoff strategi. Ange den som en sträng med formatet HH:mm:ss.
maximumInterval Den maximala fördröjningen för återförsök när du använder exponentialBackoff en strategi. Ange den som en sträng med formatet HH:mm:ss.

Här är ett exempel på en Timer-utlösarfunktion som använder en strategi för återförsök med fast fördröjning:

from azure.functions import FunctionApp, TimerRequest, Context, AuthLevel
import logging

app = FunctionApp(http_auth_level=AuthLevel.ANONYMOUS)


@app.timer_trigger(schedule="*/1 * * * * *", arg_name="mytimer",
                   run_on_startup=False,
                   use_monitor=False)
@app.retry(strategy="fixed_delay", max_retry_count="3",
           delay_interval="00:00:01")
def mytimer(mytimer: TimerRequest, context: Context) -> None:
    logging.info(f'Current retry count: {context.retry_context.retry_count}')

    if context.retry_context.retry_count == \
            context.retry_context.max_retry_count:
        logging.info(
            f"Max retries of {context.retry_context.max_retry_count} for "
            f"function {context.function_name} has been reached")
    else:
        raise Exception("This is a retryable exception")

Du kan ange dessa egenskaper för principdefinitioner för återförsök:

Property beskrivning
Strategi Obligatoriskt. Återförsöksstrategin som ska användas. Giltig värden är fixed_delay och exponential_backoff.
max_retry_count Obligatoriskt. Det maximala antalet återförsök som tillåts per funktionskörning. -1 innebär att försöka igen på obestämd tid.
delay_interval Fördröjningen som används mellan återförsök när du använder en fixed_delay strategi. Ange den som en sträng med formatet HH:mm:ss.
minimum_interval Minsta fördröjning vid återförsök när du använder en exponential_backoff strategi. Ange den som en sträng med formatet HH:mm:ss.
maximum_interval Den maximala fördröjningen för återförsök när du använder exponential_backoff en strategi. Ange den som en sträng med formatet HH:mm:ss.
@FunctionName("TimerTriggerJava1")
@FixedDelayRetry(maxRetryCount = 4, delayInterval = "00:00:10")
public void run(
    @TimerTrigger(name = "timerInfo", schedule = "0 */5 * * * *") String timerInfo,
    final ExecutionContext context
) {
    context.getLogger().info("Java Timer trigger function executed at: " + LocalDateTime.now());
}

Bindningsfelkoder

När du integrerar med Azure-tjänster kan fel komma från API:erna för de underliggande tjänsterna. Information som rör bindningsspecifika fel finns i avsnitten "Undantag och returkoder" i följande artiklar:

Nästa steg