Durable Functions: Leitfaden zur Problembehandlung

Durable Functions ist eine Erweiterung von Azure Functions, mit der Sie serverlose Orchestrierungen mithilfe von normalem Code erstellen können. Weitere Informationen zu Durable Functions finden Sie unter Übersicht zu Durable Functions.

Dieser Artikel enthält einen Leitfaden für die Problembehandlung für gängige Szenarien in Durable Functions-Apps.

Hinweis

Microsoft-Supporttechniker*innen unterstützen Sie bei Bedarf beim Diagnostizieren von Problemen mit Ihrer Anwendung. Falls Sie Ihr Problem nicht mithilfe dieses Leitfadens diagnostizieren können, können Sie im Azure-Portal auf der Seite Ihrer Funktions-App im Abschnitt Support und Problembehandlung das Blatt Neue Supportanfrage öffnen und ein Supportticket erstellen.

Screenshot of support request page in Azure Portal.

Tipp

Beim Debuggen und Diagnostizieren von Problemen sollten Sie zunächst sicherstellen, dass Ihre App die aktuelle Version der Durable Functions-Erweiterung verwendet. Die meisten bekannten Probleme, die bereits von anderen Benutzer*innen gemeldet wurden, lassen sich durch die Verwendung der aktuellen Version entschärfen. Anweisungen zum Aktualisieren Ihrer Version der Erweiterung finden Sie im Artikel Upgrade der Durable Functions-Erweiterungsversion.

Die Registerkarte Diagnose und Problembehandlung im Azure-Portal ist eine nützliche Ressource zum Überwachen und Diagnostizieren möglicher Probleme im Zusammenhang mit Ihrer Anwendung. Sie bietet basierend auf der Diagnose auch potenzielle Lösungen für Ihre Probleme. Weitere Informationen finden Sie unter Azure Functions-App-Diagnose.

Wenn Sie Ihr Problem mit den oben genannten Ressourcen nicht beheben konnten, finden Sie in den folgenden Abschnitten Empfehlungen für spezifische Anwendungssymptome:

Die Orchestrierung bleibt im Status Pending hängen.

Wenn Sie eine Orchestrierung starten, wird eine „Startnachricht“ in eine interne Warteschlange geschrieben, die von der Durable Functions-Erweiterung verwaltet wird, und der Status der Orchestrierung wird auf „Ausstehend“ gesetzt. Nachdem die Orchestrierungsnachricht von einer verfügbaren App-Instanz abgerufen und erfolgreich verarbeitet wurde, ändert sich der Status in „Wird ausgeführt“ (oder einen anderen Status, der nicht „Ausstehend“ lautet).

Führen Sie zur Problembehandlung für Orchestrierungsinstanzen, die auf unbestimmte Zeit im Status „Ausstehend“ hängen bleiben, die folgenden Schritte aus.

  • Überprüfen Sie, ob in den Durable Task Framework-Ablaufverfolgungen Warnungen oder Fehler für die betroffene Orchestrierungsinstanz-ID angezeigt werden. Eine Beispielabfrage finden Sie im Abschnitt Fehler/Warnungen in der Ablaufverfolgung.

  • Überprüfen Sie die Azure Storage-Steuerungswarteschlangen, die dem hängen gebliebenen Orchestrator zugewiesen sind, um festzustellen, ob die „Startnachricht“ noch vorhanden ist. Weitere Informationen zu Steuerungswarteschlangen finden Sie in der Dokumentation zur Steuerungswarteschlange des Azure Storage-Anbieters.

  • Ändern Sie die Version der Plattformkonfiguration Ihrer App in „64 Bit“. Manchmal werden Orchestrierungen nicht gestartet, weil die App nicht über genügend Arbeitsspeicher verfügt. Durch den Wechsel zum 64-Bit-Prozess kann die App mehr Arbeitsspeicher insgesamt belegen. Dies gilt nur für die App Service-Pläne Basic, Standard, Premium und Elastic Premium. Free- oder Verbrauchspläne unterstützen keine 64-Bit-Prozesse.

Die Orchestrierung startet nach einer langen Verzögerung.

Normalerweise werden Orchestrierungen innerhalb weniger Sekunden gestartet, nachdem sie geplant wurden. In bestimmten Fällen kann der Start von Orchestrierungen jedoch länger dauern. Führen Sie zur Problembehandlung für Orchestrierungen, deren Start mehr als ein paar Sekunden dauert, die folgenden Schritte aus.

Die Orchestrierung wird nicht abgeschlossen/bleibt im Status Running hängen.

Wenn eine Orchestrierung über einen längeren Zeitraum im Status „Wird ausgeführt“ verbleibt, bedeutet dies in der Regel, dass sie auf den Abschluss einer geplanten zeitintensiven Aufgabe wartet. Sie kann z. B. darauf warten, dass eine Aufgabe mit einem permanenten Timer, eine Aktivitätsaufgabe oder eine Aufgabe für ein externes Ereignis abgeschlossen wird. Wenn Sie jedoch feststellen, dass geplante Aufgaben erfolgreich abgeschlossen wurden, die Orchestrierung aber nicht fortgesetzt wird, liegt möglicherweise ein Problem vor, das die Orchestrierung daran hindert, mit der nächsten Aufgabe fortzufahren. Orchestrierungen in diesem Zustand werden häufig als „hängen gebliebene Orchestrierungen“ bezeichnet.

Führen Sie zur Problembehandlung für hängen gebliebene Orchestrierungen die folgenden Schritte aus:

  • Versuchen Sie, die Funktions-App neu zu starten. Dies kann hilfreich sein, wenn die Orchestrierung aufgrund eines vorübergehenden Fehlers oder Deadlocks in der App oder im Erweiterungscode hängen bleibt.

  • Überprüfen Sie die Steuerungswarteschlangen des Azure Storage-Kontos, um festzustellen, ob Warteschlangen vorhanden sind, die kontinuierlich an Umfang zunehmen. Diese KQL-Abfrage (Kusto-Abfragesprache) für Azure Storage-Nachrichten kann dabei helfen, Probleme beim Entfernen von Orchestrierungsnachrichten aus der Warteschlange zu identifizieren. Wenn das Problem nur eine einzelne Steuerungswarteschlange betrifft, kann dies auf ein Problem hindeuten, das nur für eine bestimmte App-Instanz vorliegt. In diesem Fall können Sie das Problem möglicherweise beheben, indem Sie die fehlerhafte VM-Instanz durch Hoch- oder Herunterskalieren deaktivieren.

  • Verwenden Sie die Application Insights-Abfrage im Abschnitt Azure Storage-Nachrichten, um nach diesem Warteschlangennamen als Partitions-ID zu filtern und nach Problemen im Zusammenhang mit der jeweiligen Steuerungswarteschlangenpartition zu suchen.

  • Lesen Sie den Leitfaden unter Durable Functions – bewährte Methoden und Diagnosetools. Manche Probleme werden durch bekannte Durable Functions-Antimuster verursacht.

  • Lesen Sie die Dokumentation zur Durable Functions-Versionsverwaltung. Manche Probleme werden durch Breaking Changes an aktiven Orchestrierungsinstanzen verursacht.

Die Orchestrierung wird langsam ausgeführt.

Eine umfangreiche Datenverarbeitung, interne Fehler und unzureichende Computeressourcen können dazu führen, dass Orchestrierungen langsamer als üblich ausgeführt werden. Führen Sie zur Problembehandlung für Orchestrierungen, deren Ausführung länger als erwartet dauert, die folgenden Schritte aus:

  • Überprüfen Sie, ob in den Durable Task Framework-Ablaufverfolgungen Warnungen oder Fehler für die betroffene Orchestrierungsinstanz-ID angezeigt werden. Eine Beispielabfrage finden Sie im Abschnitt Fehler/Warnungen in der Ablaufverfolgung.

  • Wenn Ihre App das In-Process-Modell von .NET verwendet, sollten Sie erwägen, erweiterte Sitzungen zu aktivieren. Erweiterte Sitzungen können Ladevorgänge für den Verlauf minimieren, durch die die Verarbeitung möglicherweise verlangsamt wird.

  • Überprüfen Sie, ob Leistungs- und Skalierbarkeitsengpässe vorliegen. Die Anwendungsleistung hängt von vielen Faktoren ab. Beispielsweise können eine hohe CPU-Auslastung oder ein hoher Arbeitsspeicherverbrauch zu Verzögerungen führen. Ausführliche Anleitungen finden Sie unter Leistung und Skalierung in Durable Functions.

Beispielabfragen

In diesem Abschnitt erfahren Sie, wie Sie Probleme beheben, indem Sie benutzerdefinierte KQL-Abfragen in der Azure Application Insights-Instanz schreiben, die für Ihre Azure Functions-App konfiguriert ist.

Azure Storage-Nachrichten

Wenn Sie den Azure Storage-Standardanbieter verwenden, wird das gesamte Verhalten von Durable Functions von Azure Storage-Warteschlangennachrichten gesteuert, und alle Status im Zusammenhang mit einer Orchestrierung werden in Tabellenspeicher und Blobspeicher gespeichert. Wenn die Durable Task Framework-Ablaufverfolgung aktiviert ist, werden alle Azure Storage-Interaktionen in Application Insights protokolliert. Diese Daten sind für das Debuggen von Ausführungs- und Leistungsproblemen von entscheidender Bedeutung.

Ab Version 2.3.0 der Durable Functions-Erweiterung können Sie diese Durable Task Framework-Protokolle in Ihrer Application Insights-Instanz veröffentlichen, indem Sie Ihre Protokollierungskonfiguration in der Datei „host.json“ aktualisieren. Informationen und Anweisungen hierzu finden Sie im Artikel Durable Task Framework-Protokollierung.

Die folgende Abfrage dient zum Untersuchen der End-to-End-Interaktionen von Azure Storage für eine bestimmte Orchestrierungsinstanz. Bearbeiten Sie start und orchestrationInstanceID, um nach Zeitbereich und Instanz-ID zu filtern.

let start = datetime(XXXX-XX-XXTXX:XX:XX); // edit this 
let orchestrationInstanceID = "XXXXXXX"; //edit this
traces  
| where timestamp > start and timestamp < start + 1h 
| where customDimensions.Category == "DurableTask.AzureStorage" 
| extend taskName = customDimensions["EventName"]
| extend eventType = customDimensions["prop__EventType"] 
| extend extendedSession = customDimensions["prop__IsExtendedSession"]
| extend account = customDimensions["prop__Account"] 
| extend details = customDimensions["prop__Details"] 
| extend instanceId = customDimensions["prop__InstanceId"] 
| extend messageId = customDimensions["prop__MessageId"] 
| extend executionId = customDimensions["prop__ExecutionId"] 
| extend age = customDimensions["prop__Age"] 
| extend latencyMs = customDimensions["prop__LatencyMs"] 
| extend dequeueCount = customDimensions["prop__DequeueCount"] 
| extend partitionId = customDimensions["prop__PartitionId"] 
| extend eventCount = customDimensions["prop__TotalEventCount"] 
| extend taskHub = customDimensions["prop__TaskHub"] 
| extend pid = customDimensions["ProcessId"]
| extend appName = cloud_RoleName
| extend newEvents = customDimensions["prop__NewEvents"]
| where instanceId == orchestrationInstanceID
| sort by timestamp asc
| project timestamp, appName, severityLevel, pid, taskName, eventType, message, details, messageId, partitionId, instanceId, executionId, age, latencyMs, dequeueCount, eventCount, newEvents, taskHub, account, extendedSession, sdkVersion

Fehler/Warnungen in der Ablaufverfolgung

Die folgende Abfrage sucht nach Fehlern und Warnungen für eine bestimmte Orchestrierungsinstanz. Sie müssen einen Wert für orchestrationInstanceID angeben.

let orchestrationInstanceID = "XXXXXX"; // edit this
let start = datetime(XXXX-XX-XXTXX:XX:XX); 
traces  
| where timestamp > start and timestamp < start + 1h
| extend instanceId = iif(isnull(customDimensions["prop__InstanceId"] ) , customDimensions["prop__instanceId"], customDimensions["prop__InstanceId"] ) 
| extend logLevel = customDimensions["LogLevel"]
| extend functionName = customDimensions["prop__functionName"]
| extend status = customDimensions["prop__status"]
| extend details = customDimensions["prop__Details"] 
| extend reason = customDimensions["prop__reason"]
| where severityLevel > 1 // to see all logs of  severity level "Information" or greater.
| where instanceId == orchestrationInstanceID
| sort by timestamp asc 

Steuerungswarteschlangen-/Partitions-ID-Protokolle

Die folgende Abfrage sucht nach allen Aktivitäten, die der Steuerungswarteschlange einer Instanz-ID (instanceID) zugeordnet sind. Sie müssen den Wert für die Instanz-ID in orchestrationInstanceID und die Startzeit der Abfrage in start angeben.

let orchestrationInstanceID = "XXXXXX"; // edit this
let start = datetime(XXXX-XX-XXTXX:XX:XX); // edit this
traces  // determine control queue for this orchestrator
| where timestamp > start and timestamp < start + 1h 
| extend instanceId = customDimensions["prop__TargetInstanceId"] 
| extend partitionId = tostring(customDimensions["prop__PartitionId"])
| where partitionId contains "control" 
| where instanceId == orchestrationInstanceID
| join kind = rightsemi(
traces  
| where timestamp > start and timestamp < start + 1h 
| where customDimensions.Category == "DurableTask.AzureStorage" 
| extend taskName = customDimensions["EventName"]
| extend eventType = customDimensions["prop__EventType"] 
| extend extendedSession = customDimensions["prop__IsExtendedSession"]
| extend account = customDimensions["prop__Account"] 
| extend details = customDimensions["prop__Details"] 
| extend instanceId = customDimensions["prop__InstanceId"] 
| extend messageId = customDimensions["prop__MessageId"] 
| extend executionId = customDimensions["prop__ExecutionId"] 
| extend age = customDimensions["prop__Age"] 
| extend latencyMs = customDimensions["prop__LatencyMs"] 
| extend dequeueCount = customDimensions["prop__DequeueCount"] 
| extend partitionId = tostring(customDimensions["prop__PartitionId"])
| extend eventCount = customDimensions["prop__TotalEventCount"] 
| extend taskHub = customDimensions["prop__TaskHub"] 
| extend pid = customDimensions["ProcessId"]
| extend appName = cloud_RoleName
| extend newEvents = customDimensions["prop__NewEvents"]
) on partitionId
| sort by timestamp asc
| project timestamp, appName, severityLevel, pid, taskName, eventType, message, details, messageId, partitionId, instanceId, executionId, age, latencyMs, dequeueCount, eventCount, newEvents, taskHub, account, extendedSession, sdkVersion

Application Insights-Spaltenreferenz

Nachfolgend finden Sie eine Liste der Spalten, die von den obigen Abfragen projiziert werden, und eine Beschreibung dieser Spalten.

Spalte Beschreibung
pid Die Prozess-ID der Funktions-App-Instanz. Hiermit können Sie ermitteln, ob der Prozess während der Ausführung einer Orchestrierung neu gestartet wurde.
taskName Der Name des protokollierten Ereignisses.
eventType Der Typ der Nachricht (stellt in der Regel die von einem Orchestrator ausgeführte Arbeit dar). Eine vollständige Liste der möglichen Werte und Beschreibungen der Werte finden Sie hier.
extendedSession Ein boolescher Wert, der angibt, ob erweiterte Sitzungen aktiviert sind.
account Das von der App verwendete Speicherkonto.
Details Zusätzliche Informationen zu einem bestimmten Ereignis (sofern verfügbar).
instanceId Die ID für eine bestimmte Orchestrierungs- oder Entitätsinstanz.
messageId Die eindeutige Azure Storage-ID für eine bestimmte Warteschlangennachricht. Dieser Wert wird am häufigsten in den Ablaufverfolgungsereignissen ReceivedMessage, ProcessingMessage und DeletingMessage angezeigt. Er ist NICHT in SendMessage-Ereignissen enthalten, da die Nachrichten-ID von Azure Storage generiert wird, nachdem die Nachricht gesendet wurde.
executionId Die ID der Orchestratorausführung (ändert sich bei jedem Aufruf von continue-as-new).
age Die Anzahl von Millisekunden seit dem Einreihen einer Nachricht in die Warteschlange. Hohe Werte deuten häufig auf Leistungsprobleme hin. Eine Ausnahme ist der TimerFired-Nachrichtentyp, der abhängig von der Timerdauer einen hohen Age-Wert aufweisen kann.
latencyMs Die Anzahl von Millisekunden, die ein Speichervorgang in Anspruch genommen hat.
dequeueCount Gibt an, wie oft eine Nachricht aus der Warteschlange entfernt wurde. Unter normalen Umständen ist dieser Wert immer 1. Bei einem anderen Wert als 1 liegt möglicherweise ein Problem vor.
partitionId Der Name der Warteschlange, die diesem Protokoll zugeordnet ist.
totalEventCount Die Anzahl von Verlaufsereignissen, die von der aktuellen Aktion betroffen sind.
taskHub Der Name Ihres Aufgabenhubs.
newEvents Eine durch Trennzeichen getrennte Liste von Verlaufsereignissen, die in die Verlaufstabelle im Speicher geschrieben werden.