Freigeben über


Singleton-Orchestratoren

Bei Hintergrundaufträgen müssen Sie häufig sicherstellen, dass jeweils nur eine Instanz eines bestimmten Orchestrators ausgeführt wird. Sie können diese Art von Singletonverhalten in Durable Functions oder den Durable Task SDKs sicherstellen, indem Sie einem Orchestrator beim Erstellen eine bestimmte Instanz-ID zuweisen und dann überprüfen, ob eine Instanz mit dieser ID bereits ausgeführt wird, bevor Sie eine neue Instanz starten.

Von Bedeutung

Derzeit ist das PowerShell Durable Task SDK nicht verfügbar.

Singleton-Beispiel

Im folgenden Beispiel wird eine HTTP-Triggerfunktion veranschaulicht, mit der eine Orchestrierung für einen Singleton-Hintergrundauftrag erstellt wird. Der Code stellt sicher, dass nur eine Instanz für eine angegebene Instanz-ID vorhanden ist.

[Function("HttpStartSingle")]
public static async Task<HttpResponseData> RunSingle(
    [HttpTrigger(AuthorizationLevel.Function, "post", Route = "orchestrators/{functionName}/{instanceId}")] HttpRequestData req,
    [DurableClient] DurableTaskClient starter,
    string functionName,
    string instanceId,
    FunctionContext executionContext)
{
    ILogger logger = executionContext.GetLogger("HttpStartSingle");

    // Check if an instance with the specified ID already exists or an existing one stopped running(completed/failed/terminated).
    OrchestrationMetadata? existingInstance = await starter.GetInstancesAsync(instanceId);
    if (existingInstance == null 
    || existingInstance.RuntimeStatus == OrchestrationRuntimeStatus.Completed 
    || existingInstance.RuntimeStatus == OrchestrationRuntimeStatus.Failed 
    || existingInstance.RuntimeStatus == OrchestrationRuntimeStatus.Terminated)
    {
        // An instance with the specified ID doesn't exist or an existing one stopped running, create one.
        string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
        await starter.ScheduleNewOrchestrationInstanceAsync(functionName, requestBody, new StartOrchestrationOptions { InstanceId = instanceId });
        logger.LogInformation($"Started orchestration with ID = '{instanceId}'.");
        return await starter.CreateCheckStatusResponseAsync(req, instanceId);
    }
    else
    {
        // An instance with the specified ID exists or an existing one still running, don't create one.
        var response = req.CreateResponse(HttpStatusCode.Conflict);
        await response.WriteStringAsync($"An instance with ID '{instanceId}' already exists.");
        return response;
    }
}

Hinweis

Der vorherige C#-Code ist für das isolierte Workermodell vorgesehen, das das empfohlene Modell für .NET-Apps ist. Weitere Informationen zu den Unterschieden zwischen den In-Process- und isolierten Worker-Modellen finden Sie im Artikel Durable Functions-Versionen.

Das folgende Beispiel zeigt, wie Sie eine Singleton-Orchestrierung mit den SdKs für dauerhafte Aufgaben erstellen. Der Code stellt sicher, dass nur eine Instanz für eine angegebene Instanz-ID vorhanden ist.

using Microsoft.DurableTask.Client;

// Check if an instance with the specified ID already exists
string instanceId = "singleton-job";
OrchestrationMetadata? existingInstance = await client.GetInstanceAsync(instanceId, getInputsAndOutputs: false);

if (existingInstance == null ||
    existingInstance.RuntimeStatus == OrchestrationRuntimeStatus.Completed ||
    existingInstance.RuntimeStatus == OrchestrationRuntimeStatus.Failed ||
    existingInstance.RuntimeStatus == OrchestrationRuntimeStatus.Terminated)
{
    // An instance with the specified ID doesn't exist or an existing one stopped running, create one.
    await client.ScheduleNewOrchestrationInstanceAsync("MyOrchestration", input, new StartOrchestrationOptions(instanceId));
    Console.WriteLine($"Started orchestration with ID = '{instanceId}'.");
}
else
{
    // An instance with the specified ID exists or an existing one still running.
    Console.WriteLine($"An instance with ID '{instanceId}' already exists.");
}

Standardmäßig werden Instanz-IDs als zufällig generierte GUIDs erstellt. Im vorherigen Beispiel wird jedoch eine bestimmte Instanz-ID verwendet. Der Code ruft dann die Orchestrierungsinstanzmetadaten ab, um zu überprüfen, ob bereits eine Instanz mit der angegebenen ID ausgeführt wird. Wenn keine solche Instanz ausgeführt wird, wird eine neue Instanz mit dieser ID erstellt.

Hinweis

In diesem Beispiel gibt es eine potenzielle Wettlaufsituation. Wenn zwei Instanzen gleichzeitig ausgeführt werden, melden beide Aufrufe möglicherweise Erfolg, aber nur eine Orchestrierungsinstanz wird tatsächlich gestartet. Je nach Ihren Anforderungen kann dies unerwünschte Nebenwirkungen haben.

Die Implementierungsdetails der Orchestratorfunktion spielen keine Rolle. Es könnte eine reguläre Orchestratorfunktion sein, die gestartet und abgeschlossen wird, oder es könnte eine sein, die für immer ausgeführt wird (d. a Eternal Orchestration). Der wichtigste Punkt ist, dass immer nur eine Instanz gleichzeitig ausgeführt wird.

Nächste Schritte