Поделиться через


Оркестраторы "синглтон"

Для фоновых заданий часто необходимо убедиться, что одновременно запускается только одна инстанция конкретного оркестратора. Это поведение можно обеспечить в Durable Functions или Durable Task SDKs путем назначения определенного идентификатора экземпляра оркестратору при его создании, и проверки, запущен ли уже экземпляр с данным идентификатором, прежде чем запускать новый экземпляр.

Это важно

В настоящее время пакет SDK для устойчивых задач PowerShell недоступен.

Пример Singleton

В следующем примере показана функция HTTP-триггера, которая создает оркестрацию одиночных фоновых задач. Код пытается убедиться, что для указанного идентификатора экземпляра существует только один активный экземпляр.

[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.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.
        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;
    }
}

Замечание

Предыдущий код C# предназначен для изолированной рабочей модели, которая является рекомендуемой моделью для приложений .NET. Дополнительные сведения о различиях между моделями рабочих процессов в процессе и изолированными моделями см. в статье о версиях Durable Functions.

В следующем примере показано, как создать однотонную оркестрацию с помощью пакетов SDK для устойчивых задач. Код пытается убедиться, что для указанного идентификатора экземпляра существует только один активный экземпляр.

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.");
}

По умолчанию идентификаторы экземпляров создаются в виде случайных GUID. Однако в предыдущем примере используется определенный идентификатор экземпляра. Затем код получает метаданные экземпляра оркестрационного процесса, чтобы проверить, запущен ли экземпляр с указанным идентификатором. Если такой экземпляр не запущен, создается новый экземпляр с таким идентификатором.

Замечание

В этом примере существует потенциальное конкурентное состояние. Если два экземпляра выполняются одновременно, оба вызова могут сообщать об успешном выполнении, но фактически запускается только один экземпляр оркестрации. В зависимости от ваших требований это может иметь нежелательные побочные эффекты.

Сведения о реализации функции оркестратора на самом деле не имеют значения. Это может быть обычная функция оркестратора, которая запускается и завершается, или та, которая выполняется постоянно (т. е. вечная оркестрация). Важно отметить, что одновременно работает только один экземпляр.

Дальнейшие действия