Rozwiązywanie typowych problemów z zestawem Durable Task SDK

Ten artykuł ułatwia diagnozowanie i rozwiązywanie typowych problemów podczas tworzenia aplikacji przy użyciu przenośnych zestawów SDK rozszerzenia Durable Task. Znajdź swój scenariusz na poniższej liście i wykonaj połączone kroki, aby zdiagnozować i rozwiązać problem.

Typowe scenariusze

Połączenie i konfiguracja

Orkiestracje

Działania

gRPC

Rejestrowanie i diagnostyka

Specyficzne dla języka

Te zestawy SDK łączą się z zapleczem Durable Task Scheduler i działają na dowolnej platformie hostującej, w tym Azure Container Apps, Kubernetes i maszynach wirtualnych.

Uwaga / Notatka

W tym przewodniku omówiono przenośne SDK Durable Task. W przypadku problemów specyficznych dla usługi Durable Task Scheduler zobacz Rozwiązywanie problemów z harmonogramem zadań trwałych. W przypadku problemów specyficznych dla rozszerzenia Durable Functions zobacz przewodnik rozwiązywania problemów Durable Functions.

Wskazówka

Panel monitorowania Durable Task Scheduler jest przydatny do sprawdzania stanu orkiestracji, wyświetlania historii wykonywania i identyfikowania awarii. Skorzystaj z niego wraz z tym przewodnikiem, aby przyspieszyć rozwiązywanie problemów.

Znajdowanie problemu

Komunikat o błędzie lub objaw Section
connection refused lub failed to connect przy uruchamianiu Emulator nie jest uruchomiony lub nie jest osiągalny
Błędy analizy parametrów połączenia lub błędy uwierzytelniania podczas uruchamiania Format parametrów połączenia jest niepoprawny
Proces roboczy łączy się, ale orkiestracje nie są uruchamiane Centrum zadań nie istnieje
błędy tożsamości/roli lub 401 Unauthorized w programie Azure Błędy uwierzytelniania oparte na tożsamości w Azure
Orkiestracja utknęła w stanie "Oczekiwanie" Orkiestracja jest zablokowana w stanie "Oczekiwanie"
Orkiestracja utknęła w stanie "Działanie" Orkiestracja jest zablokowana w stanie "Uruchomiono"
Błędy odtwarzania, pętle nieskończone lub nieoczekiwane zachowanie Niedeterministyczny kod orkiestratora
Niezgodność typów lub błędy serializacji JSON Błędy serializacji i deserializacji
activity not found Nie znaleziono działania
RESOURCE_EXHAUSTED lub message too large Przekroczono limit rozmiaru komunikatów gRPC
CANCELLED: Cancelled on client podczas zamykania Błędy anulowania strumienia podczas zamykania
CS0419 / VSTHRD105 ostrzeżenia przerywają kompilację Ostrzeżenia generatora źródła przerywają kompilacje (C#)
OrchestratorBlockedException (Java) OrchestratorBlockedException (Java)
Niepomocny błąd przy użyciu retry_policy (Python) Zasady ponawiania wymagają max_retry_interval (Python)

Problemy z połączeniem i konfiguracją

Emulator nie jest uruchomiony lub nie jest osiągalny

Jeśli aplikacja kończy się niepowodzeniem podczas uruchamiania z powodu błędu połączenia, takiego jak "odmowa połączenia" lub "nie można nawiązać połączenia", sprawdź, czy emulator harmonogramu zadań trwałej jest uruchomiony i dostępny.

  1. Sprawdź, czy kontener platformy Docker emulatora jest uruchomiony:

    docker ps | grep durabletask
    
  2. Sprawdź, czy mapowania portów są poprawne. Emulator uwidacznia dwa porty:

    • 8080 — punkt końcowy gRPC (używany przez aplikację)
    • 8082 — interfejs użytkownika pulpitu nawigacyjnego

    Jeśli używasz niestandardowego mapowania portów, zaktualizuj parametry połączenia tak, aby pasował do portu hosta mapowanego na port kontenera 8080.

  3. Przetestuj łączność z punktem końcowym gRPC:

    curl -v http://localhost:8080
    

    Odmowa połączenia wskazuje, że kontener nie jest uruchomiony lub że mapowanie portów jest nieprawidłowe.

Format parametrów połączenia jest niepoprawny

Błędy parametrów połączenia są typową przyczyną błędów uruchamiania. Sprawdź, czy łańcuch połączeń jest zgodny z oczekiwanym formatem.

Programowanie lokalne (emulator):

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

Azure (tożsamość zarządzana):

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

Azure (tożsamość zarządzana przypisana przez użytkownika):

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

Typowe błędy:

  • Używanie https dla emulatora lokalnego (emulator używa http)
  • Używanie http dla punktów końcowych Azure (Azure wymaga https)
  • Pomijanie parametru Authentication
  • Korzystanie z portu pulpitu nawigacyjnego (8082) zamiast portu gRPC (8080)

Nie udało się połączyć z klientem lub pracownikiem

Sprawdź, czy klient i proces roboczy są skonfigurowane z poprawnym parametry połączenia i nazwą Task Hub.

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

Centrum zadań nie istnieje

Jeśli orkiestracje nie mogą się uruchomić lub pracownik się łączy, ale nie wykonuje zadań, węzeł zadań może nie istnieć w harmonogramie. Emulator zwykle tworzy centra zadań automatycznie przy użyciu zmiennej środowiskowej DTS_TASK_HUB_NAMES .

Sprawdź, czy emulator został uruchomiony z poprawną nazwą centrum zadań:

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

W przypadku Azure hostowanych harmonogramów utwórz centrum zadań przy użyciu Azure CLI:

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

Błędy uwierzytelniania opartego na tożsamościach w Azure

Jeśli aplikacja działa lokalnie, ale kończy się niepowodzeniem po wdrożeniu w Azure, problem prawdopodobnie jest związany z uwierzytelnianiem:

  1. Sprawdź, czy tożsamość zarządzana jest przypisana do aplikacji (przypisana przez system lub przypisana przez użytkownika).
  2. Sprawdź, czy tożsamość ma rolę Współautor danych trwałych zadań w zasobie harmonogramu lub określonym centrum zadań.
  3. Upewnij się, że parametry połączenia używa poprawnej wartości Authentication (ManagedIdentity). W Python przekaż wystąpienie DefaultAzureCredential() jako parametr token_credential zamiast używać ciągu połączenia.
  4. W przypadku tożsamości przypisanych przez użytkownika sprawdź, czy ClientID w parametry połączenia jest zgodny z identyfikatorem klienta tożsamości.

Aby uzyskać szczegółowe instrukcje, zobacz Konfigurowanie tożsamości zarządzanej dla Durable Task Scheduler.

Problemy z orkiestracją

Orkiestracja jest zablokowana w stanie "Oczekiwanie"

Orkiestracja w stanie "Oczekiwanie" wskazuje, że została zaplanowana, ale pracownik jej nie podjął. Sprawdź następujące elementy:

  • Proces roboczy jest uruchomiony. Upewnij się, że proces roboczy jest uruchomiony i połączony z tym samym centrum zadań, w którym zaplanowano aranżację.
  • Nazwa centrum zadań pasuje. Sprawdź, czy zarówno proces roboczy, jak i klient odwołują się do tej samej nazwy centrum zadań. Niezgodność powoduje, że pracownik sonduje inne centrum zadań.
  • Program Orchestrator jest zarejestrowany. Funkcja orkiestratora lub klasa, na które powołuje się podczas planowania, musi być zarejestrowana w pracowniku.

Sprawdź, czy klasa orkiestratora jest zarejestrowana w workerze podczas uruchamiania. Jeśli używasz generatorów źródłowych ([DurableTask] atrybut), rejestracja jest automatyczna. W przeciwnym razie zarejestruj się ręcznie:

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

Orkiestracja jest utknięta w stanie "Uruchomionym"

Orkiestracja utknęła w stanie "Uruchomiona," co zwykle oznacza, że czeka na zadanie, które nie zostało ukończone. Aby zdiagnozować, otwórz pulpit nawigacyjny narzędzia Durable Task Scheduler i sprawdź historię wykonywania orkiestracji. Poszukaj ostatniego ukończonego zdarzenia — następne zdarzenie w sekwencji to to, które blokuje.

Typowe przyczyny:

  • Działanie nie zostało zarejestrowane. Orkiestracja wywołuje nazwę czynności, która nie jest zarejestrowana u pracownika. Pulpit pokazuje zdarzenie TaskScheduled bez odpowiadającego mu elementu TaskCompleted. Sprawdź, czy nazwa działania jest zgodna z kodem orkiestratora i rejestracją procesu roboczego (zobacz Nie znaleziono działania).
  • Oczekiwanie na zdarzenie zewnętrzne. Wywołanie orkiestracji wykonuje waitForExternalEvent, a zdarzenie nie zostało jeszcze wywołane. Na pulpicie wyświetla się oczekiwane zdarzenie EventRaised, ale go brakuje. Sprawdź nazwę zdarzenia i czy nadawca celuje w poprawny identyfikator wystąpienia orkiestracji.
  • Oczekiwanie na trwały czasomierz. Orkiestracja tworzy czasomierz, który jeszcze nie wygasł. Na pulpicie nawigacyjnym TimerCreated jest wyświetlane zdarzenie. Poczekaj na uruchomienie timera lub sprawdź, czy czas trwania timera jest dłuższy niż oczekiwano.
  • Działanie zgłasza nieobsługiwany wyjątek. Na pulpicie nawigacyjnym TaskFailed jest wyświetlane zdarzenie. Sprawdź szczegóły błędu pod kątem komunikatu o wyjątku i śladu stosu.

Niedeterministyczny kod orkiestratora

Kod orkiestratora musi być deterministyczny. Nieokreślony kod powoduje błędy odtwarzania, które powodują nieoczekiwane zachowanie, nieskończone pętle lub błędy. Nie używaj bieżącego czasu, liczb losowych, identyfikatorów GUID ani operacji we/wy (takich jak wywołania HTTP) bezpośrednio w kodzie orkiestratora. Użyj alternatyw dostarczanych kontekstowo lub deleguj do działań.

// ❌ 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");

Błędy serializacji i deserializacji

Błędy serializacji występują, gdy typy używane do aranżacji danych wejściowych, danych wyjściowych lub wyników działań nie są zgodne między obiektem wywołującym i wywoływanym. Te błędy mogą być wyświetlane jako nieoczekiwane null wartości, JsonExceptionlub błędy rzutowania typu w historii aranżacji.

Jak zdiagnozować:

  1. Otwórz Durable Task Scheduler dashboard i sprawdź historię orchestracji. Przyjrzyj się polam Input i Result dla działań, które zakończyły się niepowodzeniem.
  2. Sprawdź, czy typ oczekiwany przez orkiestrator jest zgodny z typem zwracanym przez działanie. Jeśli na przykład działanie zwraca string, ale orkiestrator oczekuje int, deserializacja zakończy się niepowodzeniem.
  3. Sprawdź typy, które nie są serializowalne. Typy niestandardowe, których nie można serializować do formatu JSON (na przykład typy z odwołaniami okrężnymi lub bez konstruktora domyślnego), mogą powodować niewidoczne awarie lub zgłaszać wyjątki.

Znany problem (Java): Przekazywanie bezpośrednio do aktywności może spowodować ciągi w podwójnym cudzysłowie (na przykład String zamiast "\"hello\""). To zachowanie jest znanym problemem. Rzutuj wynik jawnie lub użyj obiektów opakowania.

Wskazówka

Używaj prostych typów danych (ciągów, liczb, tablic oraz zwykłych obiektów, takich jak POJO/POCO czy obiekty danych) do orkiestracji oraz jako dane wejściowe i wyjściowe działań. Unikaj złożonych typów z niestandardową logiką serializacji.

Problemy z działaniami

Nie znaleziono działania

Jeśli aranżacja zakończy się niepowodzeniem z powodu błędu "nie znaleziono działania", nazwa działania zarejestrowana w ramach procesu roboczego nie jest zgodna z nazwą używaną w kodzie aranżacji.

W .NET działania mogą być rejestrowane według nazwy klasy lub za pomocą atrybutu [DurableTask] z generatorami źródłowymi. Sprawdź, czy klasa działań jest uwzględniona w rejestracji procesu roboczego:

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

Podczas wywoływania działania z orkiestratora użyj nazwy klasy:

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

Obsługa błędów działania

Gdy działanie zgłasza wyjątek, orkiestrator otrzymuje TaskFailedException (lub jego odpowiednik w języku). Przechwyć ten wyjątek i sprawdź szczegóły wewnętrznego błędu, aby znaleźć główną przyczynę. W języku C# użyj polecenia ex.FailureDetails , aby uzyskać dostęp do typu i komunikatu o błędzie oraz IsCausedBy<T>() sprawdzić określone typy wyjątków.

Aby uzyskać szczegółowe przykłady zasad obsługi błędów i ponawiania prób w każdym języku, zobacz Obsługa błędów i ponawianie prób.

Problemy z usługą gRPC

Przekroczono limit rozmiaru komunikatów gRPC

Jeśli wystąpi błąd RESOURCE_EXHAUSTED lub message too large, orkiestracja lub dane wejściowe/wyjściowe działania przekraczają domyślny maksymalny rozmiar komunikatu gRPC wynoszący 4 MB.

Środki zaradcze:

  • Zmniejsz rozmiar danych wejściowych i wyjściowych. Przechowuj duże ładunki w magazynie zewnętrznym, na przykład Azure Blob Storage, i przekazuj tylko odwołania.
  • Podziel duże wyniki rozgałęzień na mniejsze partie przetwarzane za pomocą pod-orchestracji.

Błędy anulowania strumienia podczas zamykania

Podczas zatrzymywania pracownika mogą wystąpić CANCELLED: Cancelled on client błędy. Te błędy są zazwyczaj nieszkodliwe i występują, gdy strumień gRPC między procesem roboczym a harmonogramem zostaje zamknięty w trakcie wyłączania. Zestawy SDK .NET, Python i Java obsługują te błędy wewnętrznie.

W języku JavaScript zestaw SDK może zgłaszać Stream error Error: 1 CANCELLED: Cancelled on client podczas wywoływania worker.stop(). Ten błąd jest znanym problemem. Owiń wywołanie zatrzymania w try-catch, jeśli błąd wpływa na logikę zamykania.

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

Rejestrowanie i diagnostyka

Szczegółowa konfiguracja rejestrowania

Zwiększ szczegółowość logów, aby uzyskać więcej szczegółów na temat operacji zestawu SDK, w tym komunikacji za pomocą gRPC i wydarzeń związanych z odtwarzaniem orkiestracji.

W pliku konfiguracji lub rejestrowania appsettings.json:

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

Użyj rejestratorów odpornych na odtwarzanie, aby uniknąć zduplikowanych wpisów dziennika podczas ponownego odtwarzania orkiestracji.

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

Integracja z usługą Application Insights

W przypadku aplikacji produkcyjnych skonfiguruj usługę Application Insights w celu zbierania danych telemetrycznych z aplikacji zestawu Durable Task SDK. Podejście integracji zależy od platformy hostingu:

Platforma hostingu Instrukcje dotyczące konfiguracji
Azure Container Apps Monitorowanie dzienników w Azure Container Apps za pomocą Log Analytics
Azure App Service Włącz rejestrowanie diagnostyczne dla aplikacji w Azure App Service
Azure Kubernetes Service Monitorowanie usługi Azure Kubernetes Service

Aby uzyskać więcej informacji na temat diagnostyki, zobacz Diagnostyka w pakietach SDK Durable Task.

Problemy specyficzne dla języka

C#

Ostrzeżenia źródłowego generatora przerywają kompilacje

Jeśli używasz <TreatWarningsAsErrors>true</TreatWarningsAsErrors> w projekcie, generatory źródeł durable task mogą generować ostrzeżenia (CS0419, VSTHRD105), które powodują przerwanie kompilacji. Pomiń te konkretne ostrzeżenia:

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

Ten znany problem jest śledzony w GitHub i został rozwiązany w nadchodzącej wersji.

Analizator Roslyn zgłasza wyjątek w pętlach foreach

Analizator Durable Task Roslyn może zgłaszać błąd ArgumentNullException , gdy kod lambda orkiestratora foreach znajduje się wewnątrz pętli. To zachowanie jest znanym problemem , który nie ma wpływu na zachowanie środowiska uruchomieniowego. Zaktualizuj do najnowszej wersji pakietu analizatora, aby uzyskać poprawkę.

Java

Błąd odmowy uprawnień w Gradle

W systemie macOS lub Linux uruchomienie ./gradlew może zakończyć się niepowodzeniem z powodu błędu "odmowa uprawnień". Napraw ten błąd, tworząc plik wykonywalny:

chmod +x gradlew

OrchestratorBlockedException

OrchestratorBlockedException występuje, gdy kod orkiestratora wykonuje operację blokującą, którą zestaw SDK wykrywa jako potencjalnie niedeterministyczną. Ten wyjątek jest zabezpieczeniem uniemożliwiającym naruszenie ograniczeń kodu orkiestratora.

Typowe przyczyny:

  • Wywoływanie blokowania zewnętrznego interfejsu API w kodzie orkiestratora.
  • Użyj Thread.sleep() bezpośrednio zamiast ctx.createTimer().
  • Wykonywanie operacji we/wy pliku lub sieci w kodzie orkiestratora.

Przenieś wszystkie operacje blokujące lub operacje wejścia/wyjścia do aktywności.

Python

Zasady ponownej próby wymagają max_retry_interval

Po skonfigurowaniu retry_policy w Python pominięcie parametru max_retry_interval generuje błąd, który wyraźnie nie wskazuje przyczyny. Zawsze określ :max_retry_interval

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
)

Zachowanie wyjątku dla WhenAllTask

W przypadku użycia when_all do równoległego uruchamiania wielu zadań, jeśli któregokolwiek z zadań nie powiedzie się, zachowanie wyjątku może nie odpowiadać oczekiwaniom. Zgłaszany jest tylko pierwszy wyjątek, a pozostałe wyjątki zadań mogą zostać utracone. Sprawdź wyniki poszczególnych zadań, jeśli potrzebujesz pełnych informacji o błędzie:

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}")

Uzyskaj pomoc techniczną

W przypadku pytań i zgłaszania usterek otwórz problem w repozytorium GitHub dla odpowiedniego zestawu SDK. W przypadku zgłaszania usterki uwzględnij następujące elementy:

  • Identyfikatory instancji orkiestracji, których dotyczy problem
  • Zakres czasu w formacie UTC pokazujący problem
  • Nazwa aplikacji i region wdrażania (jeśli jest to istotne)
  • Wersja zestawu SDK i platforma hostingu
  • Odpowiednie dzienniki zdarzeń lub komunikaty błędów
SDK Repozytorium GitHub
.NET microsoft/durabletask-dotnet
Java microsoft/durabletask-java
JavaScript microsoft/durabletask-js
Python microsoft/durabletask-python