Freigeben über


Dauerhafte Orchestrierung

Eine Orchestratorfunktion koordiniert die Ausführung anderer Funktionen als codebasierten Workflow. Orchestrator-Funktionen weisen die folgenden Merkmale auf:

  • Sie definieren Funktionsworkflows mithilfe von prozeduralen Code. Es sind keine deklarativen Schemas oder Designer erforderlich.
  • Sie können andere Funktionen synchron und asynchron aufrufen. Die Ausgabe von aufgerufenen Funktionen kann in lokalen Variablen gespeichert werden.
  • Sie sind darauf ausgelegt, dauerhaft und zuverlässig zu sein. Der Ausführungsfortschritt wird automatisch als Prüfpunkt gespeichert, wenn die Funktion einen await oder yield Operator aufruft. Der lokale Zustand geht nicht verloren, wenn der Prozess wiederverwendet oder der virtuelle Computer neu gestartet wird.
  • Sie können lang andauernd sein. Die gesamte Lebensdauer einer Orchestrierungsinstanz kann Sekunden, Tage oder Monate sein, oder Sie können die Instanz so konfigurieren, dass sie nie endet.

In diesem Artikel erhalten Sie eine Übersicht über Orchestratorfunktionen und wie sie Ihnen dabei helfen können, unterschiedliche Herausforderungen bei der App-Entwicklung zu lösen.

Informationen zu den In einer Durable Functions-App verfügbaren Funktionstypen finden Sie unter Durable Task programming model.

Tipp

Wenn Sie C# mit dem .NET-Modell für isolierte Arbeit verwenden, können Sie Orchestrierungen entweder mithilfe eines funktionsbasierten Ansatzes (statische Methoden mit [Function] Attributen) oder mit klassenbasiertem Ansatz (Klassen, von TaskOrchestrator<TInput, TOutput>denen erben) schreiben. Der klassenbasierte Ansatz erfordert das Quellgeneratorpaket "Microsoft.DurableTask.Generators " und bietet stark typierte Aufrufe. Weitere Informationen finden Sie unter Klassenbasierte Aktivitäten und Orchestrierungen. Die C#-Codebeispiele in diesem Artikel zeigen beide Ansätze.

Durable Task SDKs stellen die gleichen Orchestrierungsfunktionen wie Durable Functions bereit, werden jedoch als eigenständige Anwendungen ausgeführt und vom langlebigen Aufgabenplaner unterstützt.

Orchestrierungsidentität

Jede Instanz einer Orchestrierung weist einen Instanzbezeichner auf, der auch als Instanz-ID bezeichnet wird. Standardmäßig ist jede Instanz-ID ein automatisch generierter, global eindeutiger Bezeichner (GUID). Instanz-IDs können jedoch auch ein beliebiger vom Benutzer generierter Zeichenfolgenwert sein. Jede Orchestrierungsinstanz-ID muss innerhalb eines Aufgabenhubs eindeutig sein.

Die folgenden Regeln gelten für Instanz-IDs:

  • Sie müssen zwischen 1 und 100 Zeichen bestehen.
  • Sie müssen nicht mit @ beginnen.
  • Sie dürfen keine /, \, # oder ? Zeichen enthalten.
  • Sie dürfen keine Steuerzeichen enthalten.

Hinweis

Verwenden Sie nach Möglichkeit automatisch generierte Instanz-IDs. Vom Benutzer generierte Instanz-IDs sind für Szenarien vorgesehen, in denen es eine 1:1-Zuordnung zwischen einer Orchestrierungsinstanz und einer externen anwendungsspezifischen Entität gibt, z. B. einer Bestellung oder einem Dokument.

Hinweis

Die tatsächliche Erzwingung von Zeicheneinschränkungsregeln kann je nach dem von der App verwendeten Speicheranbieter variieren. Um das richtige Verhalten und die Kompatibilität zu gewährleisten, befolgen Sie die vorherigen Instanzen-ID-Regeln.

Die Instanz-ID einer Orchestrierung ist ein erforderlicher Parameter für die meisten Instanzverwaltungsvorgänge. Instanz-IDs sind auch für die Diagnose wichtig. Sie verwenden diese beispielsweise, wenn Sie in Application Insights Orchestrationsverfolgungsdaten durchsuchen für Problembehandlungs- oder Analysezwecke. Speichern Sie aus diesem Grund generierte Instanz-IDs an einem externen Speicherort, mit dem Sie später einfach darauf verweisen können, z. B. eine Datenbank oder Anwendungsprotokolle.

Die Instanz-ID einer Orchestrierung ist ein erforderlicher Parameter für die meisten Instanzverwaltungsvorgänge. Instanz-IDs sind auch für die Diagnose wichtig. Speichern Sie also generierte Instanz-IDs an einem externen Speicherort, der es einfacher macht, sie später zu referenzieren, z. B. eine Datenbank oder Anwendungsprotokolle.

Zuverlässigkeit

Orchestrator-Funktionen verwenden das Ereignisbeschaffungsdesignmuster , um ihren Ausführungszustand zuverlässig aufrechtzuerhalten. Anstatt den aktuellen Zustand einer Orchestrierung direkt zu speichern, verwendet das Durable Task Framework einen Append-Only-Speicher, um die vollständige Serie von Aktionen aufzuzeichnen, die die Funktions-Orchestrierung ausführt. Ein Append-Only-Speicher hat viele Vorteile im Vergleich zu dem vollständigen Dump des Laufzeitstatus. Zu den Vorteilen gehören erhöhte Leistung, Skalierbarkeit und Reaktionsfähigkeit. Außerdem erhalten Sie eventuelle Konsistenz für Transaktionsdaten, vollständige Prüfprotokolle und Verlauf. Die Prüfpfade unterstützen zuverlässige Ausgleichsmaßnahmen.

Das Durable Task Framework verwendet Event Sourcing transparent. Im Hintergrund verwendet eine Orchestratorfunktion einen await-Operator in C# und einen yield-Operator in JavaScript und Python. Diese Operatoren geben die Kontrolle des Orchestrator-Threads an den Dispatcher des Durable Task Frameworks zurück. In Java gibt das Aufrufen von .await() bei einer Aufgabe die Steuerung durch eine benutzerdefinierte Instanz von Throwable an den Dispatcher zurück. Der Dispatcher speichert dann alle neuen Aktionen, die von der Orchestratorfunktion geplant werden. Beispiele für Aktionen sind der Aufruf einer oder mehrerer untergeordneter Funktionen oder das Planen eines dauerhaften Timers. Die transparente Commitaktion aktualisiert den Ausführungsverlauf der Orchestrierungsinstanz, indem alle neuen Ereignisse an den Speicher angefügt werden, ähnlich wie bei einem reinen Anfügeprotokoll. Ebenso erstellt die Commit-Aktion Nachrichten im Speicher, um die eigentliche Arbeit zu planen. An diesem Punkt kann die Orchestratorfunktion aus dem Speicher entladen werden.

Standardmäßig verwendet Durable Functions Azure Storage als Laufzeitstatusspeicher, andere Storageanbieter werden jedoch ebenfalls unterstützt.

Wenn eine Orchestrierungsfunktion mehr Zu erledigen hat (z. B. wird eine Antwortnachricht empfangen oder ein dauerhafter Zeitgeber abläuft), wird der Orchestrator aufwachen und die gesamte Funktion von Anfang an erneut ausführen, um den lokalen Zustand neu zu erstellen. Wenn der Code während der Wiedergabe versucht, eine Funktion aufzurufen (oder andere asynchrone Arbeiten auszuführen), konsultiert das Durable Task Framework den Ausführungsverlauf der aktuellen Orchestrierung. Wenn festgestellt wird, dass die Aktivität bereits ausgeführt wurde und ein Ergebnis erzielt hat, wird das Ergebnis dieser Funktion erneut verwendet, und der Orchestratorcode läuft weiter. Die Wiedergabe wird fortgesetzt, bis der Funktionscode beendet ist oder bis eine neue asynchrone Arbeit geplant wird.

Hinweis

Damit das Wiedergabemuster ordnungsgemäß und zuverlässig funktioniert, muss Orchestratorfunktionscode deterministisch sein. Nicht deterministischer Orchestratorcode kann zu Laufzeitfehlern oder einem anderen unerwarteten Verhalten führen. Weitere Informationen zu Codeeinschränkungen für Orchestratorfunktionen finden Sie unter Orchestrator-Funktionscodeeinschränkungen.

Hinweis

Wenn eine Orchestratorfunktion Protokollmeldungen ausgibt, kann das Wiedergabeverhalten dazu führen, dass doppelte Protokollnachrichten ausgegeben werden. Informationen dazu, warum dieses Verhalten auftritt und wie Sie es umgehen können, finden Sie unter App-Protokollierung.

Orchestrierungsgeschichte

Das Ereignis-Sourcing-Verhalten des Durable Task Framework ist eng mit dem Orchestrator-Funktionscode verknüpft, den Sie schreiben. Angenommen, Sie verfügen über eine Orchestrierungsfunktion für die Verkettung von Aktivitäten, wie im folgenden Beispiel gezeigt.

Isoliertes Arbeitsmodell
[Function("HelloCities")]
public static async Task<List<string>> Run(
    [OrchestrationTrigger] TaskOrchestrationContext context)
{
    var outputs = new List<string>();

    outputs.Add(await context.CallActivityAsync<string>("SayHello", "Tokyo"));
    outputs.Add(await context.CallActivityAsync<string>("SayHello", "Seattle"));
    outputs.Add(await context.CallActivityAsync<string>("SayHello", "London"));

    // Return ["Hello Tokyo!", "Hello Seattle!", "Hello London!"].
    return outputs;
}

Klassenbasiertes Modell (isolierter Worker)

Der klassenbasierte Ansatz verwendet einen Quellgenerator und erfordert das NuGet-Paket "Microsoft.DurableTask.Generators ".

using Microsoft.DurableTask;

[DurableTask]
public class HelloCities : TaskOrchestrator<object?, List<string>>
{
    public override async Task<List<string>> RunAsync(
        TaskOrchestrationContext context, object? input)
    {
        var outputs = new List<string>();

        outputs.Add(await context.CallActivityAsync<string>("SayHello", "Tokyo"));
        outputs.Add(await context.CallActivityAsync<string>("SayHello", "Seattle"));
        outputs.Add(await context.CallActivityAsync<string>("SayHello", "London"));

        // Return ["Hello Tokyo!", "Hello Seattle!", "Hello London!"].
        return outputs;
    }
}

In-Prozess-Modell
[FunctionName("HelloCities")]
public static async Task<List<string>> Run(
    [OrchestrationTrigger] IDurableOrchestrationContext context)
{
    var outputs = new List<string>();

    outputs.Add(await context.CallActivityAsync<string>("SayHello", "Tokyo"));
    outputs.Add(await context.CallActivityAsync<string>("SayHello", "Seattle"));
    outputs.Add(await context.CallActivityAsync<string>("SayHello", "London"));

    // Return ["Hello Tokyo!", "Hello Seattle!", "Hello London!"].
    return outputs;
}
using Microsoft.DurableTask;

[DurableTask]
public class HelloCities : TaskOrchestrator<object?, List<string>>
{
    public override async Task<List<string>> RunAsync(TaskOrchestrationContext context, object? input)
    {
        var outputs = new List<string>();

        outputs.Add(await context.CallActivityAsync<string>("SayHello", "Tokyo"));
        outputs.Add(await context.CallActivityAsync<string>("SayHello", "Seattle"));
        outputs.Add(await context.CallActivityAsync<string>("SayHello", "London"));

        return outputs;
    }
}

Wenn eine Aktivitätsfunktion geplant ist, speichert das Durable Task Framework den Ausführungszustand der Funktion an verschiedenen Prüfpunkten. Bei jedem Prüfpunkt speichert das Framework den Zustand in einem dauerhaften Speicher-Back-End. Dieser Zustand wird als Orchestrierungsgeschichte bezeichnet.

Verlaufstabelle

Im Allgemeinen führt das Dauerhafte Aufgabenframework bei jedem Prüfpunkt die folgenden Aktionen aus:

  • Speichert den Ausführungsverlauf in dauerhaften Speicher.
  • Reiht Nachrichten für Funktionen ein, die der Orchestrator aufrufen soll.
  • Stellt Nachrichten für den Orchestrator selbst in die Warteschlange, z. B. dauerhafte Timer-Nachrichten.

Wenn der Prüfpunkt abgeschlossen ist, kann die Orchestratorfunktion aus dem Arbeitsspeicher entfernt werden, bis mehr Arbeit dafür erforderlich ist.

Hinweis

Azure Storage bietet keine Transaktionsgarantien hinsichtlich der Datenkonsistenz zwischen Tabellenspeicher und Warteschlangen, wenn die Daten gespeichert werden. Zur Behandlung von Ausfällen nutzt der Anbieter von Durable Functions Azure Storage Muster vom Typ Letztliche Konsistenz. Diese Muster tragen dazu bei, dass keine Daten verloren gehen, wenn ein Absturz oder ein Verbindungsverlust in der Mitte eines Prüfpunkts auftritt. Alternative Speicheranbieter wie der Durable Functions Microsoft SQL Server (MSSQL)-Speicheranbieter bieten möglicherweise stärkere Konsistenzgarantien.

Wenn die zuvor gezeigte Funktion abgeschlossen ist, sieht der Verlauf ungefähr wie die Daten in der folgenden Tabelle im Tabellenspeicher aus. Die Einträge werden zur Veranschaulichung gekürzt.

Schlüssel für Partition (InstanzID) Eventtyp Zeitstempel Input Name Ergebnis Der Status
eaee885b AusführungGestartet 2021-05-05T18:45:28.852Z NULL HelloCities
eaee885b OrchestratorStarted 2021-05-05T18:45:32.362Z
eaee885b AufgabeEingeplant 2021-05-05T18:45:32.670Z SagHallo
eaee885b OrchestratorAbgeschlossen 2021-05-05T18:45:32.670Z
eaee885b TaskCompleted 2021-05-05T18:45:34.201Z ""Hello Tokyo!"""
eaee885b OrchestratorStarted 2021-05-05T18:45:34.232Z
eaee885b AufgabeEingeplant 2021-05-05T18:45:34.435Z SagHallo
eaee885b OrchestratorAbgeschlossen 2021-05-05T18:45:34.435Z
eaee885b TaskCompleted 2021-05-05T18:45:34.763Z ""Hello Seattle!"""
eaee885b OrchestratorStarted 2021-05-05T18:45:34.857Z
eaee885b AufgabeEingeplant 2021-05-05T18:45:34.857Z SagHallo
eaee885b OrchestratorAbgeschlossen 2021-05-05T18:45:34.857Z
eaee885b TaskCompleted 2021-05-05T18:45:34.919Z ""Hello London!"""
eaee885b OrchestratorStarted 2021-05-05T18:45:35.032Z
eaee885b OrchestratorAbgeschlossen 2021-05-05T18:45:35.044Z
eaee885b AusführungAbgeschlossen 2021-05-05T18:45:35.044Z "["Hello Tokyo!"","Hello Seattle!"",""Hello London!""]" Abgeschlossen

Die Tabellenspalten enthalten die folgenden Werte:

  • PartitionKey: Die Instanz-ID der Orchestrierung.
  • EventType: Der Typ des Ereignisses. Ausführliche Beschreibungen aller Verlaufsereignistypen finden Sie unter Durable Task Framework History Events.
  • Zeitstempel: Der Zeitstempel des Ereignisses in koordinierter Weltzeit (UTC).
  • Eingabe: Die JSON-formatierte Eingabe der Funktion.
  • Name: Der Name der aufgerufenen Funktion.
  • Ergebnis: Die Ausgabe der Funktion, insbesondere der Rückgabewert.

Warnung

Diese Tabelle ist als Debuggingtool nützlich, aber das Format und der Inhalt können sich ändern, wenn sich die Durable Functions Erweiterung weiterentwickelt.

Jedes Mal, wenn die Funktion nach dem Warten auf den Abschluss einer Aufgabe fortgesetzt wird, führt das Durable Task Framework den Orchestrator erneut von vorne aus. Bei jeder erneuten Ausführung wird der Ausführungsverlauf konsultiert, um zu ermitteln, ob die aktuelle asynchrone Aufgabe abgeschlossen ist. Wenn der Ausführungsverlauf zeigt, dass die Aufgabe bereits abgeschlossen ist, gibt das Framework die Ausgabe dieser Aufgabe wieder und fährt mit der nächsten Aufgabe fort. Dieser Prozess wird fortgesetzt, bis der gesamte Ausführungsverlauf wiedergegeben wird. Nachdem der aktuelle Ausführungsverlauf wiedergegeben wurde, werden die lokalen Variablen in ihren vorherigen Werten wiederhergestellt.

Funktionen und Muster

In den folgenden Abschnitten werden die Features und Muster von Orchestratorfunktionen beschrieben.

Sub-Orchestrierungen

Orchestratorfunktionen können Aktivitätsfunktionen aufrufen, aber auch andere Orchestratorfunktionen. Sie können beispielsweise eine größere Orchestrierung aus einer Bibliothek von Orchestratorfunktionen erstellen. Sie können auch mehrere Instanzen einer Orchestratorfunktion parallel ausführen.

Weitere Informationen und Beispiele finden Sie in Suborchestrierungen in Durable Functions (Azure Functions).

Dauerhafte Timer

Orchestrierungen können dauerhafte Timer einplanen, um Verzögerungen zu implementieren oder um eine Zeitüberschreitung bei asynchronen Aktionen einzurichten. Verwenden Sie dauerhafte Zeitgeber in Orchestratorfunktionen anstelle von spracheigenen sleep APIs.

Weitere Informationen und Beispiele finden Sie unter Timers in Durable Functions (Azure Functions).

Externe Ereignisse

Orchestratorfunktionen können warten, bis externe Ereignisse eine Orchestrierungsinstanz aktualisieren. Dieses Durable Functions-Feature ist häufig nützlich für die Behandlung von menschlichen Interaktionen oder anderen externen Rückmeldungen.

Weitere Informationen und Beispiele finden Sie unter Umgang mit externen Ereignissen in Durable Functions (Azure Functions).

Fehlerbehandlung

Orchestratorfunktionen können die Fehlerbehandlungsfeatures der Programmiersprache verwenden. Vorhandene Muster wie try/catch im Orchestrierungscode werden unterstützt.

Orchestratorfunktionen können den Aktivitäts- oder untergeordneten Orchestratorfunktionen, die sie aufrufen, auch Wiederholungsrichtlinien hinzufügen. Sollte bei einer Aktivitäts- oder untergeordneten Orchestratorfunktion ein Ausnahmefehler auftreten, kann die angegebene Wiederholungsrichtlinie die Ausführung automatisch verzögern und eine bestimmte Anzahl von Wiederholungsversuchen durchführen.

Hinweis

Wenn in einer Orchestratorfunktion eine unbehandelte Ausnahme vorhanden ist, wird die Orchestrierungsinstanz in einem Failed Zustand beendet. Eine Orchestrierungsinstanz kann nach einem Fehler nicht erneut ausgeführt werden.

Weitere Informationen und Beispiele finden Sie unter Handling-Fehler in Durable Functions (Azure Functions).

Kritische Abschnitte (Durable Functions 2.x, derzeit nur .NET)

Orchestrierungsinstanzen sind auf einen Thread beschränkt, sodass Race-Bedingungen kein Problem innerhalb einer Orchestrierung darstellen. Wettlaufbedingungen sind jedoch möglich, wenn Orchestrierungen mit externen Systemen interagieren. Um Wettlaufbedingungen bei der Interaktion mit externen Systemen zu verringern, können Orchestratorfunktionen kritische Abschnitte durch Nutzung einer LockAsync-Methode in .NET definieren.

Der folgende Beispielcode zeigt eine Orchestratorfunktion, die einen kritischen Abschnitt definiert. Sie verwendet die LockAsync Methode, um den kritischen Abschnitt einzugeben. Diese Methode erfordert das Übergeben eines oder mehrerer Verweise auf eine dauerhafte Entität, die den Sperrzustand dauerhaft verwaltet. Nur eine einzelne Instanz dieser Orchestrierung kann den Code im kritischen Abschnitt gleichzeitig ausführen.

[FunctionName("Synchronize")]
public static async Task Synchronize(
    [OrchestrationTrigger] IDurableOrchestrationContext context)
{
    var lockId = new EntityId("LockEntity", "MyLockIdentifier");
    using (await context.LockAsync(lockId))
    {
        // Critical section. Only one orchestration can enter at a time.
    }
}

Die LockAsync-Methode erwirbt die dauerhaften Sperren und gibt eine IDisposable zurück, die den kritischen Abschnitt beim Entsorgen beendet. Dieses IDisposable Ergebnis kann zusammen mit einem using Block verwendet werden, um eine syntaktische Darstellung des kritischen Abschnitts zu erhalten. Wenn eine Orchestratorfunktion einen kritischen Abschnitt eingibt, kann nur eine Instanz diesen Codeblock ausführen. Alle anderen Instanzen, die versuchen, den kritischen Abschnitt einzugeben, werden blockiert, bis die vorherige Instanz den kritischen Abschnitt beendet.

Das Feature für kritische Abschnitte ist auch nützlich, um Änderungen an dauerhaften Entitäten zu koordinieren. Weitere Informationen zu kritischen Abschnitten finden Sie unter Entitätskoordination.

Hinweis

Kritische Abschnitte sind in Durable Functions 2.0 verfügbar. Derzeit implementieren nur .NET In-Process-Orchestrierungen dieses Feature. Entitäten und kritische Abschnitte sind in Durable Functions für .NET isolierte Worker-Orchestrierungen noch nicht verfügbar.

Aufrufe an HTTP-Endpunkte (Durable Functions 2.x)

Orchestrator-Funktionen dürfen keine E/A-Vorgänge ausführen, wie in Orchestrator-Funktionscodeeinschränkungen beschrieben. Die typische Problemumgehung für diese Einschränkung besteht darin, jeglichen Code, der I/O-Operationen ausführen muss, in eine Aktivitätsfunktion einzubinden. Orchestrierungen, die mit externen Systemen interagieren, verwenden häufig Aktivitätsfunktionen, um HTTP-Aufrufe zu tätigen und die Ergebnisse an die Orchestrierung zurückzugeben.

Um dieses allgemeine Muster zu optimieren, können Orchestratorfunktionen die CallHttpAsync Methode verwenden, um HTTP-APIs direkt aufzurufen.

Isoliertes Arbeitsmodell
[Function("CheckSiteAvailable")]
public static async Task CheckSiteAvailable(
    [OrchestrationTrigger] TaskOrchestrationContext context)
{
    Uri url = context.GetInput<Uri>();

    // Make an HTTP GET request to the specified endpoint.
    DurableHttpResponse response = await context.CallHttpAsync(
        method: HttpMethod.Get,
        uri: url,
        content: null,
        retryOptions: null);

    if ((int)response.StatusCode == 400)
    {
        // Handle error codes.
    }
}

In-Prozess-Modell
[FunctionName("CheckSiteAvailable")]
public static async Task CheckSiteAvailable(
    [OrchestrationTrigger] IDurableOrchestrationContext context)
{
    Uri url = context.GetInput<Uri>();

    // Make an HTTP GET request to the specified endpoint.
    DurableHttpResponse response = 
        await context.CallHttpAsync(HttpMethod.Get, url);

    if ((int)response.StatusCode == 400)
    {
        // Handle error codes.
    }
}

Neben der Unterstützung grundlegender Anforderungs-/Antwortmuster unterstützt die Methode die automatische Behandlung allgemeiner asynchroner HTTP 202-Abrufmuster. Sie unterstützt auch die Authentifizierung mit externen Diensten mithilfe von verwalteten Identitäten.

Weitere Informationen und ausführliche Beispiele finden Sie unter HTTP-Features.

Hinweis

Das direkte Aufrufen von HTTP-Endpunkten über Orchestratorfunktionen ist in Durable Functions 2.0 und höher verfügbar.

Mehrere Parameter

Es ist nicht möglich, mehrere Parameter direkt an eine Aktivitätsfunktion zu übergeben. Es wird empfohlen, ein Array mit Objekten oder mit zusammengesetzten Objekten einzugeben.

Isoliertes Arbeitsmodell

Verwenden Sie in .NET einen serialisierbaren zusammengesetzten Typ, z. B. einen Datensatz, um mehrere Parameter zu übergeben.

public record CourseInfo(string Major, int UniversityYear);

[Function("GetCourseRecommendations")]
public static async Task<object> RunOrchestrator(
    [OrchestrationTrigger] TaskOrchestrationContext context)
{
    int universityYear = context.GetInput<int>();
    CourseInfo courseInfo = new("ComputerScience", universityYear);
    object courseRecommendations = await context.CallActivityAsync<object>(
        "CourseRecommendations", courseInfo);
    return courseRecommendations;
}

In-Prozess-Modell

Verwenden Sie in .NET einen serialisierbaren zusammengesetzten Typ, um mehrere Parameter zu übergeben. Im folgenden Beispiel wird eine einfache Klasse verwendet:

public class CourseInfo
{
    public string Major { get; set; }
    public int UniversityYear { get; set; }
}

[FunctionName("GetCourseRecommendations")]
public static async Task<object> RunOrchestrator(
    [OrchestrationTrigger] IDurableOrchestrationContext context)
{
    var input = new CourseInfo
    {
        Major = "ComputerScience",
        UniversityYear = context.GetInput<int>()
    };

    object courseRecommendations = await context.CallActivityAsync<object>(
        "CourseRecommendations",
        input);
    return courseRecommendations;
}

In .NET können Sie Datensatztypen oder Tupel verwenden, um mehrere Parameter als einzelnes zusammengesetztes Objekt zu übergeben.

using Microsoft.DurableTask;

public record LocationInfo(string City, string State);

[DurableTask]
public class GetWeatherOrchestration : TaskOrchestrator<object?, string>
{
    public override async Task<string> RunAsync(TaskOrchestrationContext context, object? input)
    {
        var location = new LocationInfo("Seattle", "WA");
        string weather = await context.CallActivityAsync<string>("GetWeather", location);
        return weather;
    }
}

Nächste Schritte