Felsöka vanliga problem med Durable Task SDK

Den här artikeln hjälper dig att diagnostisera och åtgärda vanliga problem när du skapar program med bärbara Durable Task SDK:er. Hitta ditt scenario i följande lista och följ de länkade stegen för att diagnostisera och lösa problemet.

Vanliga scenarier

Anslutning och installation

Orkestreringar

Aktiviteter

gRPC

Loggning och diagnostik

Språkspecifik

Dessa SDK:er ansluter till Durable Task Scheduler serverdel och körs på valfri värdplattform, inklusive Azure Container Apps, Kubernetes och virtuella datorer.

Anmärkning

Den här guiden beskriver de bärbara SDK:erna för varaktiga uppgifter. Information om problem som är specifika för tjänsten Durable Task Scheduler finns i Felsöka durable task scheduler. Information om problem som är specifika för Durable Functions-tillägget finns i felsökningsguiden Durable Functions.

Hitta problemet

Felmeddelande eller symptom Avsnitt
connection refused eller failed to connect vid start Emulatorn körs inte eller kan inte nås
Analysfel i anslutningssträngen eller autentiseringsfel vid start Anslutningssträngformatet är felaktigt
Arbetaren ansluter men orkestreringarna startar inte Aktivitetshubben finns inte
401 Unauthorized- eller identitets-/rollfel på Azure Identitetsbaserade autentiseringsfel på Azure
Orkestrering har fastnat i "Väntar" Orkestreringen har fastnat i tillståndet "Väntande"
Orkestrering har fastnat i "Running" Orkestreringen har fastnat i läget "Körs"
Uppspelningsfel, oändliga loopar eller oväntat beteende Nondeterministisk orchestrator-kod
Typmatchningsfel eller JSON-serialiseringsfel Serialiserings- och deserialiseringsfel
activity not found Aktiviteten hittades inte
RESOURCE_EXHAUSTED eller message too large gRPC-meddelandestorleksgränsen har överskridits
CANCELLED: Cancelled on client under nedstängning Fel vid avbrytande av dataström under avstängning
CS0419 / VSTHRD105 varningar avbryter byggprocessen Källgeneratorvarningar orsakar byggfel (C#)
OrchestratorBlockedException (Java) OrchestratorBlockedException (Java)
Otydligt fel vid användning av retry_policy (Python) Retry-principen kräver max_retry_interval (Python)

Problem med anslutning och installation

Emulatorn körs inte eller kan inte nås

Om appen misslyckas vid start med ett anslutningsfel som "anslutningen nekades" eller "misslyckades att ansluta" kontrollerar du att Durable Task Scheduler-emulatorn körs och är tillgänglig.

  1. Kontrollera att docker-containern för emulatorn körs:

    docker ps | grep durabletask
    
  2. Kontrollera att portmappningarna är korrekta. Emulatorn exponerar två portar:

    • 8080 – gRPC-slutpunkt (används av din app)
    • 8082 – Instrumentpanelsgränssnitt

    Om du använder en anpassad portmappning uppdaterar du din reťazec pripojenia så att den matchar värdporten som mappas till containerporten 8080.

  3. Testa anslutningen till gRPC-slutpunkten:

    curl -v http://localhost:8080
    

    En anslutningsavslag anger att containern inte körs eller att portmappningen är felaktig.

Anslutningssträngformatet är felaktigt

Anslutningssträngsfel är en vanlig orsak till startfel. Kontrollera att din reťazec pripojenia matchar det förväntade formatet.

Lokal utveckling (emulator):

Endpoint=http://localhost:8080;Authentication=None

Azure (hanterad identitet):

Endpoint=https://<scheduler-name>.durabletask.io;Authentication=ManagedIdentity

Azure (användartilldelad hanterad identitet):

Endpoint=https://<scheduler-name>.durabletask.io;Authentication=ManagedIdentity;ClientID=<client-id>

Vanliga misstag:

  • Använda https för den lokala emulatorn (emulatorn använder http)
  • Användning av http för Azure slutpunkter (Azure kräver https)
  • Utelämna parametern Authentication
  • Använda instrumentpanelsporten (8082) i stället för gRPC-porten (8080)

Klienten eller arbetaren kan inte ansluta

Kontrollera att klienten och arbetaren har konfigurerats med rätt anslutningssträng och uppgiftshubbens namn.

using Microsoft.DurableTask.Client.AzureManaged;
using Microsoft.DurableTask.Worker.AzureManaged;

var connectionString = "Endpoint=http://localhost:8080;Authentication=None";

var builder = Host.CreateApplicationBuilder(args);

builder.Services.AddDurableTaskWorker()
    .AddTasks(registry =>
    {
        registry.AddOrchestrator<MyOrchestrator>();
        registry.AddActivity<MyActivity>();
    })
    .UseDurableTaskScheduler(connectionString);

builder.Services.AddDurableTaskClient()
    .UseDurableTaskScheduler(connectionString);

Aktivitetshubben finns inte

Om orkestreringarna inte startar eller om arbetaren ansluter men inte bearbetar arbetet kanske aktivitetshubben inte finns i schemaläggaren. Emulatorn skapar vanligtvis aktivitetshubbar automatiskt med hjälp av DTS_TASK_HUB_NAMES miljövariabeln.

Kontrollera att emulatorn startades med rätt namn på aktivitetshubben:

docker run -d -p 8080:8080 -p 8082:8082 \
  -e DTS_TASK_HUB_NAMES="my-taskhub" \
  mcr.microsoft.com/dts/dts-emulator:latest

För Azure-värdbaserade schemaläggare skapar du aktivitetshubben med hjälp av Azure CLI:

az durabletask taskhub create \
  --resource-group <resource-group> \
  --scheduler-name <scheduler-name> \
  --name <taskhub-name>

Identitetsbaserade autentiseringsfel på Azure

Om appen körs lokalt men misslyckas när den distribueras till Azure är problemet sannolikt relaterat till autentisering:

  1. Kontrollera att den hanterade identiteten har tilldelats till din app (systemtilldelad eller användartilldelad).
  2. Kontrollera att identiteten har rollen Durable Task Data Contributor för schemaläggarens resurs eller specifik uppgiftshubb.
  3. Kontrollera att reťazec pripojenia använder rätt Authentication värde (ManagedIdentity). I Python skickar du en DefaultAzureCredential()-instans som parametern token_credential i stället för att använda en reťazec pripojenia.
  4. För användartilldelade identiteter kontrollerar du att ClientID i reťazec pripojenia matchar identitetens klient-ID.

Detaljerade anvisningar finns i Konfigurera hanterad identitet för Durable Task Scheduler.

Orkestreringsproblem

Orkestreringen har fastnat i läget "Väntar"

En arbetsprocess i status "Väntar" anger att den har schemalagts men att en arbetare inte har hämtat upp den. Kontrollera följande:

  • Arbetaren är igång. Kontrollera att arbetsprocessen körs och är ansluten till samma aktivitetshubb där orkestreringen schemalagts.
  • Namnet på aktivitetshubben matchar. Kontrollera att både arbetaren och klienten refererar till samma namn på aktivitetshubben. Ett matchningsfel gör att arbetaren avsöker en annan aktivitetshubb.
  • Orchestrator har registrerats. Den orkestreringsfunktion eller -klass som refereras vid schemaläggning måste registreras med arbetaren.

Kontrollera att orchestrator-klassen har registrerats med arbetaren under starten. Om du använder källgeneratorer ([DurableTask] attribut) är registreringen automatisk. Annars registrerar du dig manuellt:

builder.Services.AddDurableTaskWorker()
    .AddTasks(registry =>
    {
        registry.AddOrchestrator<MyOrchestrator>();
        registry.AddActivity<MyActivity>();
    })
    .UseDurableTaskScheduler(connectionString);

Orkestreringen har fastnat i tillståndet "Körs"

En orkestrering som fastnat i "Running" innebär vanligtvis att den väntar på en uppgift som inte är slutförd. Om du vill diagnostisera öppnar du instrumentpanelen Durable Task Scheduler och kontrollerar orkestreringens körningshistorik. Leta efter den senast slutförda händelsen – nästa händelse i sekvensen är den som blockerar.

Vanliga orsaker:

  • Aktiviteten har inte registrerats. Orkestreringen anropar ett aktivitetsnamn som inte är registrerat hos arbetaren. Instrumentpanelen visar ett TaskScheduled-händelse utan motsvarande TaskCompleted. Kontrollera att aktivitetsnamnet matchar mellan orkestreringskoden och arbetsregistreringen (se Aktivitet hittades inte).
  • Väntar på en extern händelse. Orkestreringsanropen waitForExternalEvent och händelsen har inte startats än. Instrumentpanelen visar att en EventRaised händelse förväntas men saknas. Kontrollera händelsenamnet och att avsändaren riktar in sig på rätt orkestreringsinstans-ID.
  • Väntar på en hållbar timer. Orkestreringen skapar en timer som inte har upphört att gälla än. Instrumentpanelen visar en TimerCreated händelse. Vänta tills timern utlöses eller kontrollera om varaktigheten för timern är längre än förväntat.
  • Aktiviteten genererar ett ohanterat undantag. Instrumentpanelen visar en TaskFailed händelse. Kontrollera detaljinformationen om felet för undantagsmeddelandet och stackspårningen.

Nondeterministisk orchestrator-kod

Orchestrator-koden måste vara deterministisk. Nondeterministisk kod orsakar omspelsfel som resulterar i oväntat beteende, oändliga loopar eller fel. Använd inte aktuell tid, slumptal, GUID eller I/O (t.ex. HTTP-anrop) direkt i orchestrator-kod. Använd de sammanhangsbaserade alternativen eller delegera till aktiviteter.

// ❌ Wrong - non-deterministic
var now = DateTime.UtcNow;
var id = Guid.NewGuid();
var data = await httpClient.GetAsync("https://example.com/api");

// ✅ Correct - deterministic
var now = context.CurrentUtcDateTime;
var id = context.NewGuid();
var data = await context.CallActivityAsync<string>("FetchData");

Serialiserings- och deserialiseringsfel

Serialiseringsfel uppstår när de typer som används för orkestreringsindata, utdata eller aktivitetsresultat inte matchar mellan anroparen och den uppringda. Dessa fel kan visas som oväntade null värden, JsonException eller typecast-fel i orkestreringshistoriken.

Så här diagnostiserar du:

  1. Öppna Durable Task Scheduler-instrumentpanelen och granska orkestreringshistoriken. Titta på fälten Input och Result för aktiviteter som misslyckades.
  2. Kontrollera att den typ som förväntas av orkestratorn matchar den typ som returneras av aktiviteten. Om aktiviteten till exempel returnerar en string men orkestratorn förväntar sig en intmisslyckas deserialiseringen.
  3. Sök efter typer som inte kan serialiseras. Anpassade typer som inte kan serialiseras till JSON (till exempel typer med cirkelreferenser eller ingen standardkonstruktor) misslyckas tyst eller utlöser undantag.

Känt problem (Java): Att skicka en String direkt till en aktivitet kan resultera i strängar med dubbla citattecken (till exempel "\"hello\"" i stället för "hello"). Det här beteendet är ett känt problem. Kasta resultatet explicit eller använd omslutningsobjekt.

Tips/Råd

Använd enkla datatyper (strängar, siffror, matriser och oformaterade objekt eller POJO/POCO/dataklasser) för orkestrering och aktivitetsindata och utdata. Undvik komplexa typer med anpassad serialiseringslogik.

Aktivitetsproblem

Aktiviteten hittades inte

Om en orkestrering misslyckas med felet "aktiviteten hittades inte" matchar inte aktivitetsnamnet som registrerats med arbetaren det namn som används i orkestreringskoden.

I .NET kan aktiviteter registreras med klassnamn eller med hjälp av attributet [DurableTask] med källgeneratorer. Kontrollera att aktivitetsklassen ingår i arbetsregistreringen:

builder.Services.AddDurableTaskWorker()
    .AddTasks(registry =>
    {
        registry.AddActivity<SayHello>();
    })
    .UseDurableTaskScheduler(connectionString);

När du anropar aktiviteten från en orkestrerare, använd klassens namn:

string result = await context.CallActivityAsync<string>(nameof(SayHello), "Tokyo");

Hantering av aktivitetsfel

När en aktivitet utlöser ett undantag får orkestratorn en TaskFailedException (eller språkmotsvarighet). Fånga det här undantaget och granska den inre felinformationen för att hitta rotorsaken. I C# använder du ex.FailureDetails för att komma åt feltypen och meddelandet och IsCausedBy<T>() för att söka efter specifika undantagstyper.

Detaljerade exempel på felhantering och återförsöksprinciper på varje språk finns i Felhantering och återförsök.

gRPC-problem

gRPC-meddelandestorleksgränsen har överskridits

Om du ser ett fel av typen RESOURCE_EXHAUSTED eller message too large överskrider en orkestrering eller aktivitetsindata/utdata gRPC:s standard maximala meddelandestorlek på 4 MB.

Åtgärder:

  • Minska storleken på indata och utdata. Lagra stora nyttolaster i extern lagring, till exempel Azure Blob Storage, och skicka endast referenser.
  • Dela upp stora förgreningens resultat i mindre batchar som bearbetas via underordnade orkestreringar.

Fel vid annullering av dataström under nedstängning

När du stoppar en arbetare kan det uppstå CANCELLED: Cancelled on client fel. Dessa fel är vanligtvis ofarliga och uppstår eftersom gRPC-strömmen mellan arbetaren och schemaläggaren stängs under avstängningen. SDK:erna .NET, Python och Java hanterar dessa fel internt.

I JavaScript kan SDK:t utlösas Stream error Error: 1 CANCELLED: Cancelled on client när du anropar worker.stop(). Det här felet är ett känt problem. Omge ett stoppanrop med en try-catch om felet påverkar din avstängningslogik.

try {
  await worker.stop();
} catch (error) {
  // Ignore stream cancellation errors during shutdown
  if (!error.message.includes("CANCELLED")) {
    throw error;
  }
}

Loggning och diagnostik

Utförlig loggningskonfiguration

Öka loggverositeten för att få mer information om SDK-åtgärder, inklusive gRPC-kommunikation och orkestreringsreplikhändelser.

I din appsettings.json- eller loggningskonfigurationsfil:

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.DurableTask": "Debug"
    }
  }
}

Använd replaysäkra loggare för att undvika dubbletter av loggposter vid orkestreringsuppspelning.

public override async Task<string> RunAsync(
    TaskOrchestrationContext context, string input)
{
    ILogger logger = context.CreateReplaySafeLogger<MyOrchestrator>();
    logger.LogInformation("Processing input: {Input}", input);
    // ...
}

Application Insights-integrering

För produktionsprogram konfigurerar du Application Insights för att samla in telemetri från ditt Durable Task SDK-program. Integreringsmetoden beror på din värdplattform:

Värdplattform Installationsanvisningar
Azure Container-applikationer Övervaka loggar i Azure Container Apps med Log Analytics
Azure App-tjänst Aktivera diagnostikloggning för appar i Azure App Service
Azure Kubernetes Service Övervaka Azure Kubernetes Service

Mer information om diagnostik finns i Diagnostik i Durable Task SDK:er.

Språkspecifika problem

C#

Källgeneratorvarningar orsakar byggfel

Om du använder <TreatWarningsAsErrors>true</TreatWarningsAsErrors> i projektet kan Durable Task källkodsgeneratorer generera varningar (CS0419, VSTHRD105) som kan orsaka att bygget misslyckas. Ignorera dessa specifika varningar:

<PropertyGroup>
  <NoWarn>$(NoWarn);CS0419;VSTHRD105</NoWarn>
</PropertyGroup>

Det här kända problemet spåras på GitHub och åtgärdas i en kommande version.

Roslyn analyzer genererar foreach-loopar

Durable Task Roslyn-analysatorn kan utlösa en ArgumentNullException när orchestrator lambda-kod är placerad i en foreach slinga. Det här beteendet är ett känt problem som inte påverkar körningsbeteendet. Uppdatera till den senaste versionen av analyspaketet för att hämta korrigeringen.

Java

Fel: nekad Gradle-åtkomst

I macOS eller Linux kan körningen ./gradlew misslyckas med ett "åtkomst nekad"-fel. Åtgärda det här felet genom att göra filen körbar:

chmod +x gradlew

OrchestratorBlockedException

Det OrchestratorBlockedException inträffar när orchestrator-koden utför en blockerande operation som SDK identifierar som potentiellt icke-deterministisk. Det här undantaget är ett skydd för att förhindra att orchestrator-kod bryter mot orchestrator-kodbegränsningar.

Vanliga orsaker:

  • Anropar ett blockerande externt API i orchestrator-kod.
  • Använda Thread.sleep() direkt istället för ctx.createTimer().
  • Utför fil- eller nätverks-I/O i orchestrator-kod.

Flytta alla blockerings- eller I/O-åtgärder till aktiviteter.

Python

Återförsöksprincipen kräver max_retry_interval

När du konfigurerar en retry_policy i Python genererar utelämnande av parametern max_retry_interval ett fel som inte tydligt anger orsaken. Ange max_retry_intervalalltid :

from datetime import timedelta
from durabletask import task

retry_policy = task.RetryPolicy(
    max_number_of_attempts=3,
    first_retry_interval=timedelta(seconds=5),
    max_retry_interval=timedelta(minutes=1),  # Required
)

WhenAllTask-undantagsbeteende

När du använder when_all för att köra flera uppgifter parallellt, om en eller flera aktiviteter misslyckas, kanske undantagsbeteendet inte matchar förväntningarna. Endast det första undantaget utlöses och de återstående uppgiftsundantagen kan förloras. Granska enskilda aktivitetsresultat om du behöver fullständig felinformation:

tasks = [ctx.call_activity(process_item, input=item) for item in items]
try:
    results = yield task.when_all(tasks)
except TaskFailedError as e:
    # Only the first failure is raised
    # Check individual tasks for comprehensive error handling
    print(f"At least one task failed: {e}")

Få support

För frågor och rapportering av buggar öppnar du ett problem i GitHub lagringsplatsen för relevant SDK. När du rapporterar en bugg ska du inkludera:

  • Påverkade orkestreringsinstans-IDn
  • Tidsintervall i UTC som visar problemet
  • Programnamn och distributionsregion (om det är relevant)
  • SDK-version och värdplattform
  • Relevanta loggar eller felmeddelanden
SDK GitHub-lagringsplats
.NET microsoft/durabletask-dotnet
Java microsoft/durabletask-java
JavaScript microsoft/durabletask-js
Python microsoft/durabletask-python