Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Функция оркестратора управляет выполнением других функций в виде рабочего процесса на основе кода. Функции Оркестратора имеют следующие характеристики:
- Они определяют рабочие процессы функций с помощью процедурного кода. Декларативные схемы или конструкторы не требуются.
- Они могут вызывать другие функции синхронно и асинхронно. Выходные данные из вызываемой функции можно сохранить в локальных переменных.
- Они предназначены быть прочными и надежными. Ход выполнения автоматически сохраняется в качестве контрольной точки при вызове
awaitфункции илиyieldоператора. Локальное состояние не теряется при перезапуске процесса или перезагрузки виртуальной машины. - Они могут быть длительными. Общее время существования экземпляра оркестрации может составлять секунды, дни или месяцы, либо вы можете настроить экземпляр так, чтобы он никогда не заканчивался.
В этой статье представлены общие сведения о функциях оркестратора и способах решения различных задач разработки приложений.
Сведения о типах функций, доступных в приложении Durable Functions, см. в статье Durable Task programming model.
Подсказка
При использовании C# с изолированной рабочей моделью .NET можно создавать оркестрации с помощью подхода на основе функций (статических методов с [Function] атрибутами) или подхода на основе классов (классов, наследуемых от TaskOrchestrator<TInput, TOutput>). Для подхода на основе классов требуется пакет генератора источников Microsoft.DurableTask.Generators и обеспечивает строго типизированные вызовы. Для получения дополнительной информации см. Действия и оркестрации на основе классов. Примеры кода C# в этой статье показывают оба подхода.
SDK устойчивых задач обеспечивают те же функции оркестратора, что и Durable Functions, но работают как автономные приложения на базе Durable Task Scheduler.
Идентификация оркестрации
Каждый экземпляр оркестрации имеет идентификатор экземпляра , также известный как идентификатор экземпляра. По умолчанию каждый идентификатор экземпляра является автоматически созданным глобально уникальным идентификатором (GUID). Однако идентификаторы экземпляров также могут быть любым пользовательским строковым значением. Каждый идентификатор экземпляра оркестрации должен быть уникальным в узле задач.
Следующие правила применяются к идентификаторам экземпляров:
- Они должны быть от 1 до 100 символов.
- Они не должны начинаться с
@. - Они не должны содержать
/,\#или?символы. - Они не должны содержать символы элемента управления.
Замечание
По возможности используйте автоматически созданные идентификаторы экземпляров. Идентификаторы экземпляров, созданные пользователем, предназначены для сценариев, когда между экземпляром оркестрации и внешней сущностью, конкретной для приложения, такой как заказ на покупку или документ, существует взаимно-однозначное соответствие.
Замечание
Фактическое применение правил ограничения символов может отличаться в зависимости от поставщика хранилища , используемого приложением. Чтобы обеспечить правильное поведение и совместимость, следуйте приведенным выше правилам идентификатора экземпляра.
Идентификатор экземпляра оркестрации является обязательным параметром для большинства операций управления экземплярами. Идентификаторы экземпляров также важны для диагностирования. Например, они используются при поиске по данным отслеживания оркестрации в Application Insights для устранения неполадок или анализа. По этой причине сохраните идентификаторы созданных экземпляров во внешнем расположении, например в базе данных или логах приложений, для удобства дальнейшего обращения к ним.
Идентификатор экземпляра оркестрации является обязательным параметром для большинства операций управления экземплярами. Идентификаторы экземпляров также важны для диагностики, поэтому сохраняйте идентификаторы созданных экземпляров во внешнем расположении, что облегчает их поиск позже, например, в базе данных или журналах приложений.
Reliability
Функции оркестратора используют шаблон проектирования источник событий для надежного поддержания состояния их выполнения. Вместо прямого хранения текущего состояния оркестрации фреймворк Durable Task использует хранилище с добавлением для записи полной последовательности действий, выполняемых оркестрацией функции. Хранилище только для добавления имеет множество преимуществ по сравнению с дампингом полного состояния среды выполнения. Преимущества включают повышение производительности, масштабируемости и реагирования. Кроме того, вы получаете отложенную согласованность для транзакционных данных, полные журналы аудита и историю. Журналы аудита обеспечивают надежные компенсирующие действия.
Платформа устойчивых задач прозрачно использует ресурсы событий. За кулисами функция оркестратора использует оператор await в C# и оператор yield в JavaScript и Python. Эти операторы возвращают управление потоком оркестратора обратно в диспетчер платформы устойчивых задач. В Java вызов .await() в задаче возвращает управление диспетчеру через пользовательский экземпляр Throwable. Затем диспетчер сохраняет в хранилище любые новые действия, запланированные функцией оркестрации. Примеры действий включают вызов одной или нескольких дочерних функций или планирование устойчивого таймера. Прозрачное действие фиксации обновляет журнал выполнения экземпляра оркестрации, добавляя все новые события в хранилище, как журнал только для добавления. Аналогичным образом действие фиксации создает сообщения в хранилище для расписания выполнения фактической работы. На этом этапе функцию оркестратора можно выгрузить из памяти.
По умолчанию Durable Functions использует Azure Storage в качестве хранилища состояний среды выполнения, но другие поставщики storage также поддерживаются.
Когда функция оркестрации приобретает больше работы (например, получено сообщение с ответом или истекает срок действия устойчивого таймера), оркестратор просыпается и повторно выполняет всю функцию с начала, чтобы восстановить локальное состояние. Во время воспроизведения, если код пытается вызвать функцию (или выполнить любую другую асинхронную работу), Durable Task Framework обращается к журналу выполнения текущей оркестрации. Если он обнаружит, что действие уже выполнено и дало результат, он воспроизводит результат этой функции, а код оркестратора продолжает выполняться. Воспроизведение продолжается, пока код функции полностью не выполнится или пока не будет запланирована новая асинхронная работа.
Замечание
Чтобы шаблон воспроизведения работал правильно и надежно, код функции оркестратора должен быть детерминированным. Недетерминированный код оркестратора может привести к ошибкам среды выполнения или другому непредвиденному поведению. Дополнительные сведения об ограничениях кода для функций оркестратора см. в разделе Ограничения кода функции Orchestrator.
Замечание
Если функция оркестратора выдает сообщения журнала, поведение воспроизведения может привести к возникновению повторяющихся сообщений журнала. Сведения о том, почему такое поведение происходит и как обойти его, см. в разделе "Ведение журнала приложений".
История оркестрации
Поведение с использованием событий в платформе Durable Task тесно связано с кодом функции оркестратора, который вы пишете. Предположим, что у вас есть функция оркестратора с цепочкой действий, как показано в следующем примере.
Изолированная рабочая модель
[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;
}
Модель на основе классов (изолированная рабочая роль)
Подход на основе классов использует генератор источника и требует пакета NuGet 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;
}
}
Модель внутрипроцессного процесса
[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;
}
}
При планировании функции действия платформа устойчивых задач сохраняет состояние выполнения функции на различных контрольных точках. На каждой контрольной точке фреймворк сохраняет состояние в надёжном хранилище. Это состояние называется историей оркестрации.
Таблица истории
Как правило, платформа устойчивых задач выполняет следующие действия на каждой контрольной точке:
- Сохраняет журнал выполнения в устойчивом хранилище.
- Помещает сообщения в очередь для функций, которые оркестратор хочет вызвать.
- Помещает в очередь сообщения для самого оркестратора, например, сообщения о долговременных таймерах.
После завершения контрольной точки функция оркестратора может быть удалена из памяти, пока не будет выполнена дополнительная работа.
Замечание
Azure Storage не предоставляет никаких транзакционных гарантий согласованности данных между хранилищем таблиц и очередями при сохранении данных. Для обработки сбоев поставщик Durable Functions Azure Storage использует шаблоны итоговой согласованности. Эти шаблоны помогают гарантировать, что данные не будут потеряны при сбое или потере подключения в середине контрольной точки. Альтернативные поставщики хранилища, такие как поставщик хранилища Durable Functions поставщик хранилища Microsoft SQL Server (MSSQL, могут обеспечить более надежные гарантии согласованности.
Когда функция, показанная ранее, завершится, её история будет выглядеть примерно как данные в следующей таблице в Хранилище Таблиц. Записи сокращены для иллюстрации.
| PartitionKey (InstanceId) | Тип события | Отметка времени | Ввод | Имя | Результат | Статус |
|---|---|---|---|---|---|---|
| eaee885b | Запуск выполнен | 2021-05-05T18:45:28.852Z | null | HelloCities | ||
| eaee885b | OrchestratorStarted | 2021-05-05T18:45:32.362Z | ||||
| eaee885b | ЗадачаЗапланирована | 2021-05-05T18:45:32.670Z | Сайхелло | |||
| eaee885b | OrchestratorCompleted | 2021-05-05T18:45:32.670Z | ||||
| eaee885b | ЗадачаВыполнена | 2021-05-05T18:45:34.201Z | ""Hello Tokyo!"" | |||
| eaee885b | OrchestratorStarted | 2021-05-05T18:45:34.232Z | ||||
| eaee885b | ЗадачаЗапланирована | 2021-05-05T18:45:34.435Z | Сайхелло | |||
| eaee885b | OrchestratorCompleted | 2021-05-05T18:45:34.435Z | ||||
| eaee885b | ЗадачаВыполнена | 2021-05-05T18:45:34.763Z | """Hello Сиэтл!"" | |||
| eaee885b | OrchestratorStarted | 2021-05-05T18:45:34.857Z | ||||
| eaee885b | ЗадачаЗапланирована | 2021-05-05T18:45:34.857Z | Сайхелло | |||
| eaee885b | OrchestratorCompleted | 2021-05-05T18:45:34.857Z | ||||
| eaee885b | ЗадачаВыполнена | 2021-05-05T18:45:34.919Z | """Hello London!"" | |||
| eaee885b | OrchestratorStarted | 2021-05-05T18:45:35.032Z | ||||
| eaee885b | OrchestratorCompleted | 2021-05-05T18:45:35.044Z | ||||
| eaee885b | ВыполнениеЗавершено | 2021-05-05T18:45:35.044Z | ["Привет, Токио!", "Привет, Сиэтл!", "Привет, Лондон!"] | Завершено |
Столбцы таблицы содержат следующие значения:
- PartitionKey: идентификатор экземпляра оркестрации.
- EventType: тип события. Подробные описания всех типов исторических событий см. в разделе Durable Task Framework History Events.
- Метка времени: метка координированного универсального времени исторического события.
- Входные данные: входные данные в формате JSON функции.
- Имя: имя вызываемой функции.
- Результат: выходные данные функции, в частности, его возвращаемое значение.
Предупреждение
Эта таблица полезна как средство отладки, но его формат и содержимое могут измениться по мере развития расширения Durable Functions.
Каждый раз, когда функция возобновляется после ожидания завершения задачи, платформа устойчивых задач повторно запускает функцию оркестратора с нуля. При каждом повторном запуске он обращается к журналу выполнения, чтобы определить, завершена ли текущая асинхронная задача. Если журнал выполнения показывает, что задача уже завершена, платформа воспроизводит выходные данные этой задачи и переходит к следующей задаче. Этот процесс продолжается до тех пор, пока не будет воспроизведен весь журнал выполнения. После воспроизведения текущего журнала выполнения локальные переменные восстанавливаются до предыдущих значений.
Функции и шаблоны
В следующих разделах описываются функции и шаблоны функций оркестратора.
Подоркестрации
Функции оркестратора могут вызывать функции активности, а также другие функции оркестратора. Например, можно создать большую оркестрацию из библиотеки функций оркестратора. Кроме того, можно параллельно запускать несколько экземпляров функции оркестратора.
Дополнительные сведения и примеры см. в подоркестрациях устойчивых функций (Функции Azure).
Устойчивые таймеры
Оркестрации могут запланировать устойчивые таймеры для реализации задержек или настройки обработки времени ожидания для асинхронных действий. Используйте устойчивые таймеры в функциях оркестратора вместо родных API языка программирования sleep.
Дополнительные сведения и примеры см. в разделе Таймеры в Durable Functions (Azure Functions).
Внешние события
Функции оркестратора могут ожидать внешних событий для обновления экземпляра оркестрации. Эта функция Durable Functions часто полезна для обработки взаимодействия с пользователями или других внешних обратных вызовов.
Для получения дополнительной информации и примеров см. раздел Обработка внешних событий в Durable Functions (Azure Functions).
Обработка ошибок
Функции оркестратора могут использовать функции обработки ошибок языка программирования. Существующие шаблоны, например try/catch , поддерживаются в коде оркестрации.
Функции оркестратора также могут добавлять политики повторных попыток в функции активности или в подчиненные функции оркестрации, которые они вызывают. Если действие или функция подоркестратора завершается ошибкой с исключением, указанная политика повторных попыток может автоматически отложить выполнение и повторить его до указанного количества раз.
Замечание
Если в функции оркестратора существует необработанное исключение, экземпляр оркестрации завершается в Failed состоянии. Экземпляр оркестрации не может быть перезапущен после сбоя.
Для получения дополнительной информации и примеров см. раздел Обработка ошибок в Durable Functions (Azure Functions).
Критические разделы (Durable Functions 2.x, в настоящее время только .NET)
Экземпляры оркестрации являются однопоточными, поэтому условия гонки не являются проблемой в оркестрации. Однако условия гонки возможны, когда оркестрации взаимодействуют с внешними системами. Чтобы снизить условия гонки при взаимодействии с внешними системами, функции оркестратора могут определять критические разделы с помощью метода LockAsync в .NET.
В следующем примере кода показана функция оркестратора, определяющая критически важный раздел. Он использует LockAsync метод для ввода критического раздела. Этот метод требует передачи одной или нескольких ссылок на устойчивую сущность, которая может управлять состоянием блокировки. Только один экземпляр этого оркестрации может выполнять код в критическом разделе одновременно.
[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.
}
}
Метод LockAsync получает устойчивые блокировки и возвращает IDisposable, который заканчивает критическую секцию при удалении. Этот IDisposable результат можно использовать вместе с блоком using для получения синтаксического представления критического раздела. Когда функция оркестратора входит в критически важный раздел, только один экземпляр может выполнять этот блок кода. Любые другие экземпляры, которые пытаются войти в критическую секцию, блокируются до тех пор, пока предыдущий экземпляр не выйдет из критической секции.
Функция критической секции также полезна для координации изменений долговечных объектов. Дополнительные сведения о критических разделах см. в разделе "Координация сущностей".
Замечание
Критические разделы доступны в Durable Functions 2.0. В настоящее время только внутрипроцессные оркестрации .NET реализуют эту функцию. Сущности и критические разделы пока недоступны в устойчивых функциях для изолированных рабочих оркестров .NET.
Вызовы конечных точек HTTP (Durable Functions 2.x)
Функции Оркестратора не разрешены для операций ввода-вывода, как описано в ограничениях кода функции Orchestrator. Обычное решение для этого ограничения заключается в том, чтобы упаковать любой код, который должен выполнять операции ввода-вывода в функцию действия. Оркестрации, взаимодействующие с внешними системами, часто используют функции активности для вызова HTTP и возврата результатов в оркестрацию.
Чтобы упростить этот распространенный шаблон, функции оркестратора могут использовать CallHttpAsync метод для вызова API-интерфейсов HTTP напрямую.
Изолированная рабочая модель
[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.
}
}
Модель внутрипроцессного процесса
[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.
}
}
Помимо поддержки базовых шаблонов запросов и ответов, метод поддерживает автоматическую обработку распространенных асинхронных шаблонов опроса HTTP 202. Она также поддерживает проверку подлинности с помощью внешних служб с помощью управляемых удостоверений.
Дополнительные сведения и подробные примеры см. в разделе "Функции HTTP".
Замечание
Вызов конечных точек HTTP непосредственно из функций оркестратора доступен в Durable Functions 2.0 и в более поздних версиях.
Несколько параметров
Невозможно передать несколько параметров в функцию действия напрямую. Рекомендация заключается в передаче массива объектов или составных объектов.
Изолированная рабочая модель
В .NET используйте сериализуемый составной тип, например запись, для передачи нескольких параметров.
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;
}
Модель внутрипроцессного процесса
В .NET используйте сериализуемый составной тип для передачи нескольких параметров. В следующем примере используется простой класс:
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;
}
В .NET можно использовать типы записей или кортежи для передачи нескольких параметров в виде одного составного объекта.
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;
}
}