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.
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.
Lesen Sie in der Dokumentation zu verzögerten Orchestrierungen in Azure Storage nach, ob die Verzögerung möglicherweise auf bekannte Einschränkungen zurückzuführen ist.
Überprüfen Sie, ob in den Durable Task Framework-Ablaufverfolgungen Warnungen oder Fehler mit der betroffenen Orchestrierungsinstanz-ID angezeigt werden. Eine Beispielabfrage finden Sie im Abschnitt Fehler/Warnungen in der Ablaufverfolgung.
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. |