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


Версионирование оркестрации (предварительная версия)

Ключевая область, которая следует учитывать при использовании устойчивой системы оркестрации, заключается в том, как обрабатывать обновление и понижение уровня оркестрации. При прерывании оркестрации и последующем возобновлении (например, во время обновления узла) планировщик устойчивых задач воспроизводит события оркестрации. Это делается для обеспечения надежности — система воспроизводит, чтобы обеспечить успешного выполнения всех предыдущих шагов до того, как будет выполнен следующий шаг, что является основным обещанием парадигмы надежного выполнения. Таким образом, если управление процессом изменяется между развертываниями, шаги, которые оно предпринимает, могут отличаться. Если это произойдет, система бросит NonDeterministicError вместо того, чтобы оркестрация продолжалась.

Управление версиями оркестрации помогает предотвратить проблемы, связанные с недетерминизмом, позволяя беспрепятственно работать с новыми (или старыми) оркестрациями. Планировщик устойчивых задач имеет два разных стиля версирования, которые будут рассмотрены ниже. Обратите внимание, что различные стили управления версиями можно использовать отдельно или вместе.

Это важно

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

Это важно

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

Это важно

В настоящее время управление версиями недоступно в пакете SDK для Python.

Условное управление версиями, основанное на клиенте или контексте

Чтобы оркестрация имела версию, сначала ее нужно установить в клиенте. Для пакета SDK для .NET это выполняется с помощью стандартных расширений построителя узлов, как показано ниже:

Замечание

Доступно в пакете SDK для .NET (Microsoft.DurableTask.Client.AzureManaged) с версии 1.9.0.

builder.Services.AddDurableTaskClient(builder =>
{
    builder.UseDurableTaskScheduler(connectionString);
    builder.UseDefaultVersion("1.0.0");
});

Замечание

Доступно в пакете SDK для Java (com.microsoft:durabletask-client) с версии 1.6.0.

public DurableTaskClient durableTaskClient(DurableTaskProperties properties) {
    // Create client using Azure-managed extensions
    return DurableTaskSchedulerClientExtensions.createClientBuilder(properties.getConnectionString())
        .defaultVersion("1.0")
        .build();
}

После добавления оркестрации, инициированной этим хостом, будет использоваться версия 1.0.0. Сама версия является простой строкой и принимает любое значение. Однако пакет SDK попытается преобразовать его в System.Version.NET. Если его можно преобразовать, эта библиотека используется для сравнения, если нет, используется простое сравнение строк.

Предоставляя версию в клиенте, она также становится доступной в TaskOrchestrationContext. Это означает, что версия может использоваться в условных инструкциях. До тех пор, пока более новые версии оркестрации имеют соответствующую проверку версий, как старая, так и новая версия оркестрации могут работать вместе на одном хосте. Пример использования версии:

[DurableTask]
class HelloCities : TaskOrchestrator<string, List<string>>
{
    private readonly string[] Cities = ["Seattle", "Amsterdam", "Hyderabad", "Kuala Lumpur", "Shanghai", "Tokyo"];

    public override async Task<List<string>> RunAsync(TaskOrchestrationContext context, string input)
    {
        List<string> results = [];
        foreach (var city in Cities)
        {
            results.Add(await context.CallSayHelloAsync($"{city} v{context.Version}"));
            if (context.CompareVersionTo("2.0.0") >= 0)
            {
                results.Add(await context.CallSayGoodbyeAsync($"{city} v{context.Version}"));
            }
        }

        Console.WriteLine("HelloCities orchestration completed.");
        return results;
    }
}
public TaskOrchestration create() {
    return ctx -> {
        List<String> results = new ArrayList<>();
        for (String city : new String[]{ "Seattle", "Amsterdam", "Hyderabad", "Kuala Lumpur", "Shanghai", "Tokyo" }) {
            results.add(ctx.callActivity("SayHello", city, String.class).await());
            if (VersionUtils.compareVersions(ctx.getVersion(), "2.0.0") >= 0) {
                // Simulate a delay for newer versions
                results.add(ctx.callActivity("SayGoodbye", city, String.class).await());
            }
        }
        ctx.complete(results);
    };
}

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

Когда следует использовать управление версиями клиентов

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

Версионирование на основе рабочего узла

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

  1. Версия самого воркера
  2. Версия по умолчанию, которая будет применена к подоргестрациям, запущенным рабочим процессом
  3. Стратегия, которую будет использовать работник для сопоставления с версией оркестрации
  4. Стратегия, которую должен предпринять работник, если версия не соответствует стратегии сопоставления

Ниже приведены различные стратегии сопоставления.

Имя Описание
Отсутствует Версия не учитывается при обработке работы
Строгий Версия оркестрации и рабочего модуля должна точно совпадать
ТекущаяИлиБолееСтарая Версия в оркестрации должна быть не больше версии в рабочем узле.

Ниже приведены различные стратегии сбоев.

Имя Описание
Отклонение Оркестрация будет отклонена рабочим процессом, но останется в рабочей очереди для повторной попытки позже.
Сбой Оркестрация будет завершена с ошибкой и удалена из очереди задач.

Как и в случае с версиями клиента, все они задаются с помощью стандартного шаблона построителя узлов:

Замечание

Доступно в пакете SDK для .NET (Microsoft.DurableTask.Worker.AzureManaged) с версии 1.9.0.

builder.Services.AddDurableTaskWorker(builder =>
{
    builder.AddTasks(r => r.AddAllGeneratedTasks());
    builder.UseDurableTaskScheduler(connectionString);
    builder.UseVersioning(new DurableTaskWorkerOptions.VersioningOptions
    {
        Version = "1.0.0",
        DefaultVersion = "1.0.0",
        MatchStrategy = DurableTaskWorkerOptions.VersionMatchStrategy.Strict,
        FailureStrategy = DurableTaskWorkerOptions.VersionFailureStrategy.Reject,
    });
});

Замечание

Доступно в пакете SDK для Java (com.microsoft:durabletask-client) с версии 1.6.0.

private static DurableTaskGrpcWorker createTaskHubServer() {
    DurableTaskGrpcWorkerBuilder builder = new DurableTaskGrpcWorkerBuilder();
    builder.useVersioning(new DurableTaskGrpcWorkerVersioningOptions(
            "1.0",
            "1.0",
            DurableTaskGrpcWorkerVersioningOptions.VersionMatchStrategy.CURRENTOROLDER,
            DurableTaskGrpcWorkerVersioningOptions.VersionFailureStrategy.REJECT));

    // Orchestrations can be defined inline as anonymous classes or as concrete classes
    builder.addOrchestration(new TaskOrchestrationFactory() {
        @Override
        public String getName() { return "HelloCities"; }

        @Override
        public TaskOrchestration create() {
            return ctx -> {
                List<String> results = new ArrayList<>();
                for (String city : new String[]{ "Seattle", "Amsterdam", "Hyderabad", "Kuala Lumpur", "Shanghai", "Tokyo" }) {
                    results.add(ctx.callActivity("SayHello", city, String.class).await());
                }
                ctx.complete(results);
            };
        }
    });

    // Activities can be defined inline as anonymous classes or as concrete classes
    builder.addActivity(new TaskActivityFactory() {
        @Override
        public String getName() { return "SayHello"; }

        @Override
        public TaskActivity create() {
            return ctx -> {
                String input = ctx.getInput(String.class);
                return "Hello, " + input + "!";
            };
        }
    });

    return builder.build();
}

Reject Стратегия сбоя должна использоваться, когда необходимо, чтобы оркестрация попыталась снова позже или на другом рабочем модуле. Когда оркестрация отклоняется, она просто возвращается в рабочую очередь. Когда он снова извлечен из очереди, он может попасть к другому работнику или снова к тому же самому. Процесс будет повторяться до тех пор, пока не станет доступен работник, который сможет справиться с оркестровкой. Эта стратегия позволяет беспрепятственно управлять процессами развертывания, в которых происходит обновление оркестрации. По мере выполнения развертывания рабочие, которые не могут обработать оркестрацию, отклонят его, а рабочие, которые могут обработать его, будут его обрабатывать. Возможность использования смешанных версий рабочих и оркестрации позволяет выполнять такие сценарии, как сине-зеленые развертывания.

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

Когда следует использовать версионирование рабочих процессов

Управление рабочими версиями должно использоваться в сценариях, когда оркестрации неизвестной или неподдерживаемой версии не должны выполняться вообще. Вместо того чтобы размещать код управления версиями в рабочем процессе, версия рабочего процесса останавливает оркестрацию еще до начала выполнения. Это позволяет значительно упростить управление кодом. Без каких-либо изменений кода различные сценарии развертывания можно обрабатывать, например синие зеленые развертывания, упомянутые ранее.