Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Управление версиями в Устойчивые функции важно, так как функции неизбежно добавляются, удаляются и изменяются в течение времени существования приложения. Устойчивые функции позволяет объединять функции в цепочку способами, которые ранее не были возможны, и эта цепочка влияет на способ обработки управления версиями.
Эта статья поможет вам:
- Определите, является ли изменение кода критическим изменением.
- Выберите правильную стратегию устранения рисков для безопасного развертывания.
Быстрое сравнение стратегий
Если вы уже знаете, что ваше изменение приводит к сбоям, используйте эту таблицу, чтобы выбрать стратегию смягчения последствий.
| Стратегия | лучше всего подходит для | Сведения |
|---|---|---|
| Версионирование оркестрации (рекомендуется) | Большинство приложений с критическими изменениями. Встроенная функция времени выполнения совместима с любым бэкэндом хранилища. | Переход к разделу |
| Параллельное развертывание | Приложения, которые не могут использовать управление версиями оркестрации или которые нуждаются в полной изоляции с помощью отдельных центров задач или учетных записей хранения. | Переход к разделу |
| Остановка всех экземпляров в тестовом режиме | Прототипирование и локальная разработка, где потеря в полетных оркестрациях является приемлемой. | Переход к разделу |
Подсказка
Если вы ищете встроенную функцию управления версиями оркестрации, которая обеспечивает автоматическую изоляцию версий на уровне среды выполнения, см. Управление версиями оркестрации.
Это важно
Перед развертыванием проверьте, является ли изменение критическим:
- Вы изменили имя, тип входных данных или тип выходных данных функции действия или сущности?
- Вы добавили, удалили или переупорядочили вызовы действий, подоркестраций, таймеров или внешних событий в коде оркестратора?
- Вы переименовали или удалили функцию, которую всё ещё могут вызывать выполняющиеся оркестрации?
Если вы ответили да на любой из них, используйте одну из стратегий смягчения последствий, приведенных ниже, чтобы избежать сбоев в выполнении оркестрации.
Типы критических изменений
Существует несколько примеров критических изменений. В этой статье рассматриваются наиболее распространенные типы. Основная тема заключается в том, что изменения в коде функций влияют как на новые, так и на существующие оркестрации функций.
Изменения сигнатуры операции или функции сущности
Изменение подписи относится к изменению имени, входных данных или выходных данных функции. Если вы вносите такого рода изменение в функцию активности или сущности, это может нарушить любую функцию оркестратора, зависящую от данного изменения. Это поведение особенно верно для типовобезопасных языков. Если вы обновите функцию оркестратора, чтобы вместить это изменение, можно разбить существующие экземпляры в тестовом режиме.
В качестве примера рассмотрим следующую функцию оркестратора.
[FunctionName("FooBar")]
public static Task Run([OrchestrationTrigger] IDurableOrchestrationContext context)
{
bool result = await context.CallActivityAsync<bool>("Foo");
await context.CallActivityAsync("Bar", result);
}
Эта функция принимает результат Foo и передает его в Bar. Предположим, что необходимо изменить возвращаемое значение Foo из логического элемента в строку, чтобы поддерживать более широкий спектр значений результатов. Результат выглядит следующим образом:
[FunctionName("FooBar")]
public static Task Run([OrchestrationTrigger] IDurableOrchestrationContext context)
{
string result = await context.CallActivityAsync<string>("Foo");
await context.CallActivityAsync("Bar", result);
}
Это изменение работает хорошо для всех новых экземпляров функции оркестратора, но может нарушить любые экземпляры в тестовом режиме. Например, рассмотрим случай, когда экземпляр оркестрации вызывает функцию с именем Foo, получает логическое значение и затем устанавливает контрольную точку. Если изменение подписи развертывается на этом этапе, экземпляр контрольной точки завершается сбоем сразу после возобновления и воспроизведения вызова Foo. Это происходит из-за того, что результат таблицы журнала является логическим значением, но новый код пытается десериализировать его в строковое значение, что приводит к неожиданному поведению или даже исключению среды выполнения для типобезопасных языков.
Этот пример — один из многих случаев, когда изменение сигнатуры функции может нарушить работу существующих экземпляров. Как правило, если оркестратор должен изменить способ вызова функции, то изменение, скорее всего, будет проблематичным.
Изменения в логике оркестратора
Другой класс проблем управления версиями возникает от изменения кода функции оркестратора таким образом, чтобы изменить путь выполнения для экземпляров в тестовом режиме.
Рассмотрим следующую функцию оркестратора:
[FunctionName("FooBar")]
public static Task Run([OrchestrationTrigger] IDurableOrchestrationContext context)
{
bool result = await context.CallActivityAsync<bool>("Foo");
await context.CallActivityAsync("Bar", result);
}
Теперь предположим, что необходимо добавить новый вызов функции между двумя существующими вызовами функций.
[FunctionName("FooBar")]
public static Task Run([OrchestrationTrigger] IDurableOrchestrationContext context)
{
bool result = await context.CallActivityAsync<bool>("Foo");
if (result)
{
await context.CallActivityAsync("SendNotification");
}
await context.CallActivityAsync("Bar", result);
}
Это изменение добавляет новый вызов функции SendNotification между Foo и Bar. Изменений подписи нет. Проблема возникает, когда существующий экземпляр возобновляется после вызова Bar. При повторном воспроизведении, если исходный вызов Foo вернул true, то оркестратор вызывает SendNotification, что отсутствует в его истории выполнения. Среда выполнения обнаруживает эту несогласованность и вызывает ошибку недетерминированной оркестрации, потому что она столкнулась с вызовом SendNotification, когда ожидался вызов Bar. Такая же проблема может возникнуть при добавлении вызовов API к другим долговечным операциям, как, например, при создании долговечных таймеров, ожидании внешних событий или вызовах вложенных оркестраций.
Стратегии устранения рисков
Предупреждение
Развертывание радикальных изменений без стратегии их смягчения (подход "ничего не делать") может вызвать отказ оркестрации из-за недетерминированных ошибок, привести к ее зависанию в неопределенном Running состоянии или инициировать низкоуровневые сбои, ухудшающие производительность. При развертывании критических изменений всегда используйте одну из следующих стратегий.
Версионирование оркестрации (рекомендуется)
В отличие от других стратегий в этом разделе, версионирование оркестрации является встроенной функцией среды выполнения, которая обеспечивает автоматическую изоляцию версий. Вам не нужно управлять отдельными развертываниями, центрами задач или учетными записями хранения. Вместо этого среда выполнения отслеживает сведения о версии и гарантирует, что экземпляры оркестрации обрабатываются совместимыми работниками.
При оркестрации версионирования:
- Каждый экземпляр оркестрации получает версию, постоянно связанную с ним при создании.
- Функции Оркестратора могут проверять их версию и выполнение ветви соответствующим образом, сохраняя старые и новые пути кода в той же базе кода.
- Работники, использующие более новые версии функций оркестратора, могут продолжать выполнять экземпляры оркестрации, созданные более старыми версиями.
- Среда выполнения запрещает рабочим, работающим с более старыми версиями функций оркестратора, выполнять оркестрации более новых версий.
Этот подход требует минимальной конфигурации (строки версии и необязательной стратегии сопоставления) и совместим с любым поставщиком хранилища. Рекомендуется использовать стратегию для приложений, которые должны поддерживать критические изменения при сохранении развертываний без простоев.
Подробные инструкции по настройке и реализации см. в разделе "Управление версиями".
Остановка всех экземпляров в тестовом режиме
Другим вариантом является остановка всех экземпляров во время полета. Если вы используете поставщик служба хранилища Azure по умолчанию для Устойчивые функции, остановите все экземпляры, очищая содержимое внутренних очередей control-queue и workitem-queue. Кроме того, остановите приложение-функцию, удалите эти очереди и перезапустите приложение. Очереди создаются автоматически после перезапуска приложения. Предыдущие экземпляры оркестрации могут оставаться в состоянии "Выполнение" неограниченное время, но они не засоряют журнал сообщений о сбоях и не причиняют вред вашему приложению. Этот подход идеально подходит для быстрой разработки прототипов, включая локальную разработку.
Предупреждение
Этот подход требует прямого доступа к базовым ресурсам хранилища и не подходит для всех поставщиков хранилища, поддерживаемых Устойчивые функции.
Параллельное развертывание
Самый надежный способ обеспечить безопасное развертывание критических изменений заключается в развертывании их параллельно с более старыми версиями. Вы можете использовать любой из следующих методов:
- Другая учетная запись хранения: разверните все обновления в качестве нового приложения-функции с другой учетной записью хранения. Это полностью изолирует состояние новой версии от старой версии.
- Другой концентратор задач: разверните новую копию приложения-функции с той же учетной записью хранения, но с обновленным именем концентратора задач . Этот подход создает новые артефакты хранилища для новой версии, пока старая версия продолжает использовать существующие артефакты.
При параллельном развертывании в Azure можно использовать слоты deployment для одновременного запуска обеих версий только с одним в качестве активного слота production. Когда вы будете готовы предоставить новую логику оркестрации, переключите новую версию в рабочий слот.
Замечание
В этом руководстве используются термины служба хранилища Azure, но обычно применяются ко всем поддерживаемым поставщикам хранилища Устойчивые функции.
Замечание
Переключения слотов развертывания лучше всего работают с триггерами HTTP и веб-перехватчика. Для триггеров, отличных от HTTP, таких как очереди или Центры событий, определение триггера должно быть производным от параметра приложения , который обновляется в рамках операции переключения.