Freigeben über


Leistung und Skalierung in Durable Functions (Azure Functions)

Um Leistung und Skalierbarkeit zu optimieren, verstehen Sie das Skalierungsverhalten von Durable Functions. In diesem Artikel wird erläutert, wie der Functions-Host Worker auf der Grundlage der Last skaliert, und wie verschiedene Einstellungen angepasst werden können.

Workerskalierung

Ein wichtiger Vorteil des Aufgabenhub-Konzepts ist, dass die Anzahl der Mitarbeiter, die Aufgabenhubarbeitselemente verarbeiten, nach oben und unten skaliert wird. Anwendungen fügen Instanzen hinzu (Skalieren nach außen), um die Verarbeitung der Arbeit zu beschleunigen, und entfernen Instanzen (Skalieren nach innen), wenn nicht genügend Arbeit vorhanden ist, um sie auszulasten. Sie können sogar auf Null skalieren , wenn der Aufgabenhub im Leerlauf ist. Wenn Sie auf Null skalieren, werden keine Worker ausgeführt. Nur der Skalierungscontroller und speicher bleiben aktiv.

Dieses Konzept wird im folgenden Diagramm veranschaulicht:

Diagramm, das zeigt, wie Worker für einen Aufgabenhub auf- und abwärts sowie auf Null skaliert werden.

Autoskalierung

In den Plänen "Verbrauch" und "Elastic Premium" unterstützt Durable Functions die Automatische Skalierung über den Azure Functions Scale Controller. Der Skalierungscontroller überwacht, wie lange Nachrichten und Aufgaben vor der Verarbeitung warten. Basierend auf diesen Latenzen werden Mitarbeiter hinzugefügt oder entfernt.

Hinweis

Ab Durable Functions 2.0 können Sie Funktions-Apps so konfigurieren, dass sie in VNet-geschützten Dienstendpunkten im Elastic Premium-Plan ausgeführt werden. In dieser Konfiguration starten die Durable Functions-Trigger Skalierungsanforderungen anstelle des Skalierungscontrollers. Weitere Informationen finden Sie unter Runtime-Skalierungsüberwachung.

Im Premium-Plan hält die automatische Skalierung die Anzahl der Mitarbeiter (und Betriebskosten) ungefähr proportional zur Auslastung der Anwendung.

CPU-Auslastung

Orchestrator-Funktionen führen ihre Logik mehrmals aus, da sie wiederholt werden. Daher ist es wichtig, dass Orchestrator-Funktionsthreads keine CPU-intensiven Aufgaben ausführen, keine E/A durchführen oder blockieren. Verschieben Sie Arbeit, die E/A, Blockierung oder mehrere Threads erfordern kann, in Aktivitätsfunktionen.

Aktivitätsfunktionen verhalten sich wie normale, in der Warteschlange ausgelöste Funktionen. Sie unterstützen E/A, CPU-intensive Vorgänge und mehrere Threads. Da Aktivitätstrigger zustandslos sind, skalieren sie auf viele VMs.

Entitätsfunktionen laufen auch auf einem einzelnen Thread und führen Operationen nacheinander aus. Entitätsfunktionen haben keine Einschränkungen für den Codetyp, den sie ausführen.

Funktion-Timeouts

Aktivitäts-, Orchestrator- und Entitätsfunktionen unterliegen denselben Funktionstimeouts wie andere Azure-Funktionen. Durable Functions behandelt ein Funktionstimeout wie eine unbehandelte Ausnahme im Code.

Wenn z. B. bei einer Aktivität eine Zeitüberschreitung auftritt, zeichnet Durable Functions die Ausführung als fehlgeschlagen auf und benachrichtigt den Orchestrator. Der Orchestrator behandelt die Zeitüberschreitung wie jede andere Ausnahme: Die Laufzeit versucht, den Vorgang zu wiederholen, wenn der Aufruf dies angibt, oder es wird ein Exception Handler ausgeführt.

Batchverarbeitung von Entitätsvorgängen

Um die Leistung zu verbessern und Kosten zu senken, kann eine einzelne Arbeitsaufgabe eine Reihe von Entitätsvorgängen ausführen. Im Verbrauchsplan wird jeder Batch als einzelne Funktionsausführung abgerechnet.

Standardmäßig beträgt die maximale Batchgröße 50 im Verbrauchsplan und 5.000 für andere Pläne. Sie können auch die maximale Batchgröße in der host.json Datei konfigurieren. Wenn die maximale Batchgröße auf „1“ festgelegt wird, ist die Batchverarbeitung faktisch deaktiviert.

Hinweis

Wenn einzelne Entitätsvorgänge lange dauern, kann es hilfreich sein, die maximale Batchgröße einzuschränken, um das Risiko von Funktionstimeouts zu verringern, insbesondere im Verbrauchsplan.

Zwischenspeicherung von Instanzen

Zum Verarbeiten einer Orchestrierungsarbeitsaufgabe führt ein Worker zwei Dinge aus:

  1. Orchestrierungshistorie abrufen.
  2. Wiederholung des Orchestratorcodes mithilfe des Verlaufs.

Wenn derselbe Arbeiter mehrere Arbeitselemente für dieselbe Orchestrierung verarbeitet, kann der Speicheranbieter den Verlauf im Arbeitsspeicher des Arbeiters zwischenspeichern, um den ersten Schritt zu überspringen. Es kann auch den Orchestrator während der Ausführung zwischenspeichern, um zu vermeiden, dass der Verlauf für nachfolgende Arbeitselemente erneut abgespielt wird.

Das Zwischenspeichern reduziert typischerweise die I/O-Operationen auf den zugrunde liegenden Speicherdienst und verbessert dadurch den Durchsatz und die Latenz. Es erhöht aber auch die Speichernutzung der Mitarbeiter.

Der Azure Storage-Anbieter und der Netherite-Speicheranbieter unterstützen das Zwischenspeichern von Instanzen. Die Tabelle vergleicht Anbieter.

Azure Storage Anbieter Netherite-Speicheranbieter MSSQL-Speicheranbieter
Zwischenspeichern von Instanzen Unterstützt
(nur .NET-In-Process-Worker)
Unterstützt Nicht unterstützt
Standardeinstellung Deaktiviert Aktiviert
Mechanismus Erweiterte Sitzungen Instanzcache
Dokumentation Erweiterte Sitzungen anzeigen Siehe Instanzcache

Tipp

Die Zwischenspeicherung kann die Anzahl der Wiederholungen des Verlaufs durch die Laufzeit reduzieren, Wiederholungen können jedoch nicht völlig eliminiert werden. Testen Sie während der Entwicklung Orchestratoren mit deaktivierter Zwischenspeicherung. Die erzwungene Wiedergabe hilft Ihnen, Verstöße gegen Orchestratorfunktionscodeeinschränkungen zu erkennen.

Zwischenspeicherungsmechanismen im Vergleich

Die Anbieter verwenden verschiedene Mechanismen, um Zwischenspeicherung zu implementieren und verschiedene Parameter zum Konfigurieren des Cacheverhaltens anzubieten.

  • Erweiterte Sitzungen, die vom Azure Storage-Anbieter verwendet werden, behalten Mid-Execution-Orchestratoren im Arbeitsspeicher, bis diese für eine bestimmte Zeit untätig sind. Steuern Sie dieses Verhalten mit extendedSessionsEnabled und extendedSessionIdleTimeoutInSeconds. Ausführliche Informationen finden Sie in der Azure Storage-Anbieterdokumentation unter dem Abschnitt 'Erweiterte Sitzungen'.

Hinweis

Erweiterte Sitzungen werden nur im .NET In-Process-Worker unterstützt.

  • Der vom Netherite-Speicheranbieter verwendete Instanzcache behält den Instanzstatus und den Verlauf im Arbeitsspeicher des Mitarbeiters bei und verfolgt die Gesamtspeichernutzung. Wenn der Cache den InstanceCacheSizeMB Grenzwert überschreitet, werden die zuletzt verwendeten Instanzdaten entfernt. Wenn Sie CacheOrchestrationCursors auf true setzen, speichert der Cache auch die Mid-Execution-Orchestratoren. Ausführliche Informationen finden Sie in der Dokumentation zum Instanzcache in der Dokumentation des Netherite-Speicheranbieters.

Hinweis

Instanzencaches funktionieren mit allen Sprach-SDKs, die Option CacheOrchestrationCursors ist jedoch nur für den .NET In-Process-Worker verfügbar.

Drosselungen der Parallelität

Eine einzelne Arbeitsinstanz kann mehrere Arbeitsaufgaben gleichzeitig ausführen. Dies erhöht Parallelität und nutzt Arbeitsressourcen effizienter. Wenn ein Worker jedoch zu viele Arbeitsaufgaben gleichzeitig verarbeitet, kann er Ressourcen wie CPU, Netzwerkverbindungen und Arbeitsspeicher ausschöpfen.

Damit ein einzelner Worker nicht überlastet wird, müssen Sie möglicherweise die Parallelität pro Instanz drosseln. Die Anzahl der gleichzeitig auf jedem Arbeiter ausgeführten Funktionen einzuschränken, hilft zu vermeiden, dass die Ressourcengrenzen dieses Arbeiters erreicht werden.

Hinweis

Einschränkungen der Parallelität gelten nur lokal und beschränken die laufenden Prozesse pro Worker. Daher beschränken sie den Gesamten Systemdurchsatz nicht.

Tipp

In einigen Fällen kann die Drosselung der Parallelität pro Arbeitskraft tatsächlich den Gesamtdurchsatz des Systems erhöhen . Dies kann der Fall sein, wenn jeder Worker weniger Aufgaben übernimmt, sodass der Skalierungscontroller weitere Worker hinzufügt, um mit den Warteschlangen Schritt zu halten, was wiederum den Gesamtdurchsatz erhöht.

Konfiguration der Drosselung

Konfigurieren Von Aktivitäts-, Orchestrator- und Entitätsfunktions-Parallelitätsgrenzwerten in der host.json Datei. Verwenden Sie durableTask/maxConcurrentActivityFunctions für Aktivitätsfunktionen und durableTask/maxConcurrentOrchestratorFunctions für Orchestrator- und Entitätsfunktionen. Diese Einstellungen beschränken die Anzahl der Orchestrator-, Entitäts- und Aktivitätsfunktionen, die ein Worker in den Arbeitsspeicher lädt.

Hinweis

Orchestrierungen und Entitäten werden nur während der Verarbeitung von Ereignissen oder Vorgängen in den Arbeitsspeicher geladen, oder wenn das Zwischenspeichern von Instanzen aktiviert ist. Nachdem sie ihre Logik ausgeführt haben und dann auf (z. B. await in C# oder yield in JavaScript und Python) gewartet haben, können sie aus dem Arbeitsspeicher entfernt werden. Entladene Orchestrierungen und Entitäten zählen nicht für die maxConcurrentOrchestratorFunctions-Drosselung. Auch wenn sich Millionen von Instanzen im Zustand „Wird ausgeführt“ befinden, werden nur Instanzen im Arbeitsspeicher für das Drosselungslimit gezählt. Eine Orchestrierung, die auf den Abschluss einer Aktivität wartet, zählt nicht für die Drosselung.

Funktionen 2.0

{
  "extensions": {
    "durableTask": {
      "maxConcurrentActivityFunctions": 10,
      "maxConcurrentOrchestratorFunctions": 10
    }
  }
}

Funktionen 1.x

{
  "durableTask": {
    "maxConcurrentActivityFunctions": 10,
    "maxConcurrentOrchestratorFunctions": 10
  }
}

Sprachlaufzeitüberlegungen

Die ausgewählte Sprachlaufzeit kann strenge Parallelitätseinschränkungen für Ihre Funktionen festlegen. Beispielsweise können Durable Functions Apps, die in Python oder PowerShell geschrieben wurden, jeweils nur eine Funktion auf einer einzelnen VM ausführen. Dies kann zu Leistungsproblemen führen, wenn Sie dies nicht berücksichtigen. Wenn ein Orchestrator zehn Aktivitäten vorsieht, die Sprach-Laufzeit aber nur eine Funktion zulässt, müssen neun der zehn Aktivitätsfunktionen warten, bis sie ausgeführt werden können. Außerdem können diese wartenden Aktivitäten nicht per Load Balancing auf andere Prozesse verteilt werden, da die Durable Functions-Laufzeit sie bereits in den Arbeitsspeicher lädt. Dies ist besonders problematisch, wenn die Aktivitätsfunktionen lange andauern.

Wenn ihre Sprachlaufzeit die Parallelität einschränkt, aktualisieren Sie Durable Functions Parallelitätseinstellungen, um sie abzugleichen. Dadurch wird verhindert, dass die Durable Functions-Laufzeit mehr Funktionen gleichzeitig ausführt, als die Sprachlaufzeit zulässt, und ausstehende Aktivitäten können gleichmäßig auf andere VMs verteilt werden. Wenn eine Python-App beispielsweise die Parallelität auf vier Funktionen einschränkt (z. B. 4 Threads in einem Arbeitsprozess mit einer Sprache oder 1 Thread für 4 Spracharbeitsprozesse), konfigurieren Sie sowohl maxConcurrentOrchestratorFunctions als auch maxConcurrentActivityFunctions auf 4.

Informationen zu Python Leistungsempfehlungen finden Sie unter Improve throughput performance of Python apps in Azure Functions. Diese Techniken können Durable Functions Leistung und Skalierbarkeit erheblich verbessern.

Partitionsanzahl

Einige Speicheranbieter unterstützen die Partitionierung und ermöglichen ihnen das Festlegen partitionCount.

Bei der Partitionierung konkurrieren Die Mitarbeiter nicht um einzelne Arbeitsaufgaben. Das Partitionieren gruppiert Arbeitselemente in partitionCount Partitionen, und der Ladevorgang weist diese Partitionen den Workern zu. Dieser Ansatz reduziert die Gesamtanzahl der Speicherzugriffe. Außerdem kann er Instanzspeicherung aktivieren und die Lokalität verbessern, da Affinität erschaffen wird: Der gleiche Worker verarbeitet alle Workitems für dieselbe Instanz.

Hinweis

Partitionierungsgrenzwerte werden aufskaliert, weil nur partitionCount-Worker Arbeitselemente aus einer partitionierten Warteschlange verarbeiten können.

Die folgende Tabelle zeigt, welche Warteschlangen von jedem Speicheranbieter partitioniert werden, sowie den zulässigen Bereich und die Standardwerte für partitionCount.

Azure Storage Anbieter Netherite-Speicheranbieter MSSQL-Speicheranbieter
Instanznachrichten Partitioniert Partitioniert Nicht partitioniert
Aktivitätsmeldungen Nicht partitioniert Partitioniert Nicht partitioniert
Standard partitionCount 4 12
Maximale partitionCount 16 32
Dokumentation Siehe Horizontale Skalierung des Orchestrators Siehe Überlegungen zur Partitionsanzahl

Warnung

Sie können die Partitionsanzahl nach dem Erstellen eines Aufgabenhubs nicht mehr ändern. Legen Sie es hoch genug fest, um die erwarteten Skalierungsanforderungen für die Task Hub-Instanz zu erfüllen.

Konfigurieren der Partitionsanzahl

Geben Sie in der Datei partitionCount an. Der folgende host.json codeausschnitt legt durableTask/storageProvider/partitionCount (oder durableTask/partitionCount in Durable Functions 1.x) auf 3 fest.

Dauerhafte Funktionen 2.x

{
  "extensions": {
    "durableTask": {
      "storageProvider": {
        "partitionCount": 3
      }
    }
  }
}

Dauerhafte Funktionen 1.x

{
  "extensions": {
    "durableTask": {
      "partitionCount": 3
    }
  }
}

Minimieren der Aufruflatenz

Aufrufanforderungen für Aktivitäten, Orchestratoren und Entitäten werden in der Regel schnell abgeschlossen, aber die Aufruflatenz hängt vom Skalierungsverhalten des App Service-Plans, den Parallelitätseinstellungen und der Backloggröße Ihrer Anwendung ab. Verwenden Sie Stresstests , um die Taillatenz Ihrer Anwendung zu messen und zu reduzieren.

Leistungsziele

Wenn Sie eine Produktions-App mit Durable Functions planen, sollten Sie die Leistungsanforderungen frühzeitig berücksichtigen. Diese grundlegenden Nutzungsszenarien helfen Ihnen bei der Planung:

  • Sequenzielle Aktivitätsausführung: In diesem Szenario wird eine Orchestratorfunktion beschrieben, die eine Reihe von Aktivitätsfunktionen sequenziell ausführt. Es ähnelt am ehesten dem Funktionskettenbeispiel .
  • Parallele Aktivitätsausführung: In diesem Szenario wird eine Orchestratorfunktion beschrieben, die viele Aktivitätsfunktionen parallel mithilfe des Fan-out-, Fan-In-Musters ausführt.
  • Parallele Antwortverarbeitung: Dieses Szenario ist die zweite Hälfte des Fan-out-Fan-In-Musters. Es konzentriert sich auf die Fan-in-Leistung. Im Gegensatz zu Fanout wird fan-in in einer einzigen Orchestratorfunktionsinstanz ausgeführt, sodass sie auf einer einzelnen VM ausgeführt wird.
  • Externe Ereignisverarbeitung: Dieses Szenario stellt eine einzelne Orchestratorfunktionsinstanz dar, die jeweils auf externe Ereignisse wartet.
  • Verarbeitung von Entitätsvorgängen: In diesem Szenario wird getestet, wie schnell eine einzelneCounter-Entität einen konstanten Vorgangsstrom verarbeiten kann.

Durchsatznummern für diese Szenarien befinden sich in der Dokumentation des Speicheranbieters. Dies gilt insbesondere für:

Tipp

Im Gegensatz zu Fan-Out-Operationen sind Fan-In-Operationen auf eine einzelne virtuelle Maschine beschränkt. Wenn in Ihrer Anwendung das Muster „Auffächern nach außen/innen (Fan-out, Fan-in)“ verwendet wird und Sie die Leistung im Hinblick auf die Auffächerung nach innen optimieren möchten, können Sie die Auffächerung der Aktivitätsfunktionen nach außen in mehrere untergeordnete Orchestrierungen unterteilen.

Nächste Schritte