Ограничения кода функции OrchestratorOrchestrator function code constraints

Устойчивые функции — это расширение функций Azure , которое позволяет создавать приложения с отслеживанием состояния.Durable Functions is an extension of Azure Functions that lets you build stateful apps. Функцию Orchestrator можно использовать для координации выполнения других устойчивых функций в приложении-функции.You can use an orchestrator function to orchestrate the execution of other durable functions within a function app. Функции Orchestrator поддерживают отслеживание состояния, надежность и потенциально длительное выполнение.Orchestrator functions are stateful, reliable, and potentially long-running.

Ограничения кода оркестратораOrchestrator code constraints

Функции Orchestrator используют источники событий для обеспечения надежного выполнения и поддержания состояния локальной переменной.Orchestrator functions use event sourcing to ensure reliable execution and to maintain local variable state. Поведение воспроизведения кода Orchestrator создает ограничения на тип кода, который можно написать в функции Orchestrator.The replay behavior of orchestrator code creates constraints on the type of code that you can write in an orchestrator function. Например, функции Orchestrator должны быть детерминированными: функция Orchestrator будет воспроизведена несколько раз, и она должна выдавать один и тот же результат каждый раз.For example, orchestrator functions must be deterministic: an orchestrator function will be replayed multiple times, and it must produce the same result each time.

Использование детерминированных интерфейсов APIUsing deterministic APIs

В этом разделе приводятся некоторые простые рекомендации по обеспечению детерминированности кода.This section provides some simple guidelines that help ensure your code is deterministic.

Функции Orchestrator могут вызывать любой API на своих целевых языках.Orchestrator functions can call any API in their target languages. Однако важно, чтобы функции Orchestrator вызывали только детерминированные API.However, it's important that orchestrator functions call only deterministic APIs. Детерминированный API — это API, который всегда возвращает одно и то же значение при вводе одних и тех же входных данных независимо от того, когда или как часто он вызывается.A deterministic API is an API that always returns the same value given the same input, no matter when or how often it's called.

В следующей таблице приведены примеры интерфейсов API, которые следует избегать, поскольку они не являются детерминированными.The following table shows examples of APIs that you should avoid because they are not deterministic. Эти ограничения относятся только к функциям Orchestrator.These restrictions apply only to orchestrator functions. Другие типы функций не имеют таких ограничений.Other function types don't have such restrictions.

Категория APIAPI category ПричинаReason Возможное решениеWorkaround
Даты и времяDates and times API, возвращающие текущую дату или время, являются недетерминированными, поскольку возвращаемое значение отличается для каждого воспроизведения.APIs that return the current date or time are nondeterministic because the returned value is different for each replay. Используйте APICurrentUtcDateTime в .NET или API currentUtcDateTime в JavaScript, который является надежным для воспроизведения.Use theCurrentUtcDateTime API in .NET or the currentUtcDateTime API in JavaScript, which are safe for replay.
Идентификаторы GUID и UUIDGUIDs and UUIDs API-интерфейсы, возвращающие случайный идентификатор GUID или UUID, являются недетерминированными, поскольку сформированное значение отличается для каждого воспроизведения.APIs that return a random GUID or UUID are nondeterministic because the generated value is different for each replay. Для безопасного создания случайных идентификаторов GUID используйте NewGuid в .NET или newGuid в JavaScript.Use NewGuid in .NET or newGuid in JavaScript to safely generate random GUIDs.
Случайные числаRandom numbers API-интерфейсы, возвращающие случайные числа, являются недетерминированными, поскольку сформированное значение отличается для каждого воспроизведения.APIs that return random numbers are nondeterministic because the generated value is different for each replay. Используйте функцию действия для возврата случайных чисел в согласование.Use an activity function to return random numbers to an orchestration. Возвращаемые значения функций действий всегда являются надежными для воспроизведения.The return values of activity functions are always safe for replay.
ПривязкиBindings Входные и выходные привязки обычно выполняют операции ввода-вывода и являются недетерминированными.Input and output bindings typically do I/O and are nondeterministic. Функция Orchestrator не должна напрямую использовать даже клиент оркестрации и привязки клиента сущности .An orchestrator function must not directly use even the orchestration client and entity client bindings. Используйте входные и выходные привязки внутри функций клиента или действия.Use input and output bindings inside client or activity functions.
СетьNetwork Сетевые вызовы содержат внешние системы и являются недетерминированными.Network calls involve external systems and are nondeterministic. Используйте функции действий для выполнения сетевых вызовов.Use activity functions to make network calls. Если необходимо выполнить HTTP-вызов из функции Orchestrator, можно также использовать устойчивые API HTTP.If you need to make an HTTP call from your orchestrator function, you also can use the durable HTTP APIs.
Блокирующие APIBlocking APIs Блокирующие интерфейсы API, такие как Thread.Sleep в .NET и аналогичные API, могут вызвать проблемы производительности и масштабирования для функций Orchestrator, и их следует избегать.Blocking APIs like Thread.Sleep in .NET and similar APIs can cause performance and scale problems for orchestrator functions and should be avoided. В плане потребления функций Azure они могут даже привести к ненужной оплате времени выполнения.In the Azure Functions Consumption plan, they can even result in unnecessary runtime charges. Используйте альтернативы для блокирования API, когда они доступны.Use alternatives to blocking APIs when they're available. Например, используйте CreateTimer, чтобы ввести задержки при выполнении согласования.For example, use CreateTimer to introduce delays in orchestration execution. Устойчивые задержки таймера не учитываются во время выполнения функции Orchestrator.Durable timer delays don't count towards the execution time of an orchestrator function.
Асинхронные APIAsync APIs Код Orchestrator никогда не должен запускать асинхронную операцию, за исключением использования IDurableOrchestrationContext API или API объекта context.df.Orchestrator code must never start any async operation except by using the IDurableOrchestrationContext API or the context.df object's API. Например, нельзя использовать Task.Run, Task.Delayи HttpClient.SendAsync в .NET или setTimeout и setInterval в JavaScript.For example, you can't use Task.Run, Task.Delay, and HttpClient.SendAsync in .NET or setTimeout and setInterval in JavaScript. Платформа устойчивых задач запускает код Orchestrator в одном потоке.The Durable Task Framework runs orchestrator code on a single thread. Он не может взаимодействовать с другими потоками, которые могут вызываться другими асинхронными API.It can't interact with any other threads that might be called by other async APIs. Функция Orchestrator должна делать только устойчивые асинхронные вызовы.An orchestrator function should make only durable async calls. Функции действий должны выполнять любые другие асинхронные вызовы API.Activity functions should make any other async API calls.
Асинхронные функции JavaScriptAsync JavaScript functions Нельзя объявлять функции JavaScript в качестве async, поскольку среда выполнения Node. js не гарантирует, что асинхронные функции являются детерминированными.You can't declare JavaScript orchestrator functions as async because the node.js runtime doesn't guarantee that asynchronous functions are deterministic. Объявите функции в JavaScript Orchestrator как функции синхронного генератора.Declare JavaScript orchestrator functions as synchronous generator functions.
API-интерфейсы потоковThreading APIs Платформа устойчивых задач запускает код Orchestrator в одном потоке и не может взаимодействовать с другими потоками.The Durable Task Framework runs orchestrator code on a single thread and can't interact with any other threads. Введение новых потоков в выполнение оркестрации может привести к недетерминированному выполнению или взаимоблокировкам.Introducing new threads into an orchestration's execution can result in nondeterministic execution or deadlocks. Функции Orchestrator практически никогда не используют API-интерфейсы потоков.Orchestrator functions should almost never use threading APIs. Если такие API необходимы, ограничьте их использование только функциями действий.If such APIs are necessary, limit their use to only activity functions.
Статические переменныеStatic variables Избегайте использования неконстантных статических переменных в функциях Orchestrator, так как их значения могут меняться со временем, что приводит к недетерминированному поведению во время выполнения.Avoid using nonconstant static variables in orchestrator functions because their values can change over time, resulting in nondeterministic runtime behavior. Используйте константы или ограничьте использование статических переменных функциями действий.Use constants, or limit the use of static variables to activity functions.
Переменные средыEnvironment variables Не используйте переменные среды в функциях Orchestrator.Don't use environment variables in orchestrator functions. Их значения со временем могут меняться, что приводит к недетерминированному поведению во время выполнения.Their values can change over time, resulting in nondeterministic runtime behavior. Ссылки на переменные среды должны осуществляться только в клиентских функциях или функциях действий.Environment variables must be referenced only from within client functions or activity functions.
Бесконечные циклыInfinite loops Избегайте бесконечных циклов в функциях оркестраторов.Avoid infinite loops in orchestrator functions. Так как платформа устойчивых задач сохраняет журнал выполнения в ходе выполнения функции оркестрации, бесконечный цикл может привести к нехватке памяти для экземпляра Orchestrator.Because the Durable Task Framework saves execution history as the orchestration function progresses, an infinite loop can cause an orchestrator instance to run out of memory. Для сценариев бесконечного цикла используйте API-интерфейсы, такие как ContinueAsNew в .NET или continueAsNew в JavaScript, чтобы перезапустить выполнение функции и отменить предыдущий журнал выполнения.For infinite loop scenarios, use APIs like ContinueAsNew in .NET or continueAsNew in JavaScript to restart the function execution and to discard previous execution history.

Хотя применение этих ограничений на первый взгляд может показаться затруднительным, на практике их легко отслеживать.Although applying these constraints might seem difficult at first, in practice they're easy to follow.

Платформа устойчивых задач пытается обнаружить нарушения предыдущих правил.The Durable Task Framework attempts to detect violations of the preceding rules. Если обнаруживается нарушение, платформа создает исключение нондетерминистикорчестратионексцептион .If it finds a violation, the framework throws a NonDeterministicOrchestrationException exception. Однако это поведение не будет перехватывать все нарушения, и вам не следует зависеть от него.However, this detection behavior won't catch all violations, and you shouldn't depend on it.

Управление версиямиVersioning

Устойчивое оркестрации может выполняться непрерывно в течение дней, месяцев, лет или даже етерналли.A durable orchestration might run continuously for days, months, years, or even eternally. Любые обновления кода, внесенные в Устойчивые функции приложения, влияющие на незавершенные оркестрации, могут нарушить поведение воспроизведения оркестрации.Any code updates made to Durable Functions apps that affect unfinished orchestrations might break the orchestrations' replay behavior. Именно поэтому важно тщательно спланировать при внесении обновлений в код.That's why it's important to plan carefully when making updates to code. Более подробное описание способов версии кода см. в статье Управление версиями.For a more detailed description of how to version your code, see the versioning article.

Устойчивые задачиDurable tasks

Примечание

Этот раздел содержит сведения о внутренней реализации платформы устойчивых задач.This section describes internal implementation details of the Durable Task Framework. Вы можете использовать устойчивые функции, не зная этих сведений.You can use durable functions without knowing this information. Она предназначена только для того, чтобы помочь вам понять поведение воспроизведения.It is intended only to help you understand the replay behavior.

Задачи, которые могут безопасно ожидать в функциях Orchestrator, иногда называют устойчивыми задачами.Tasks that can safely wait in orchestrator functions are occasionally referred to as durable tasks. Платформа устойчивых задач создает и управляет этими задачами.The Durable Task Framework creates and manages these tasks. Примерами являются задачи, возвращаемые каллактивитясинк, ваитфорекстерналевенти CreateTimer в функциях .NET Orchestrator.Examples are the tasks returned by CallActivityAsync, WaitForExternalEvent, and CreateTimer in .NET orchestrator functions.

Эти устойчивые задачи внутренне управляются списком объектов TaskCompletionSource в .NET.These durable tasks are internally managed by a list of TaskCompletionSource objects in .NET. Во время воспроизведения эти задачи создаются в ходе выполнения кода Orchestrator.During replay, these tasks are created as part of orchestrator code execution. Они завершаются, так как диспетчер перечисляет соответствующие события журнала.They're finished as the dispatcher enumerates the corresponding history events.

Задачи выполняются синхронно с помощью одного потока, пока не будут воспроизведены все журналы.The tasks are executed synchronously using a single thread until all the history has been replayed. Для устойчивых задач, которые не завершены в конце воспроизведения журнала, выполняются соответствующие действия. Например, сообщение может быть поставлено в очередь для вызова функции действия.Durable tasks that aren't finished by the end of history replay have appropriate actions carried out. For example, a message might be enqueued to call an activity function.

Описание поведения во время выполнения в этом разделе должно помочь понять, почему функция Orchestrator не может использовать await или yield в неустойчивой задаче.This section's description of runtime behavior should help you understand why an orchestrator function can't use await or yield in a nondurable task. Существует две причины: поток Dispatcher не может дождаться завершения задачи, а любой обратный вызов этой задачи может повредить состояние отслеживания функции Orchestrator.There are two reasons: the dispatcher thread can't wait for the task to finish, and any callback by that task might potentially corrupt the tracking state of the orchestrator function. Для обнаружения этих нарушений используются некоторые проверки среды выполнения.Some runtime checks are in place to help detect these violations.

Чтобы узнать больше о том, как платформа устойчивых задач выполняет функции Orchestrator, просмотрите Исходный код устойчивой задачи на сайте GitHub.To learn more about how the Durable Task Framework executes orchestrator functions, consult the Durable Task source code on GitHub. В частности, см. раздел TaskOrchestrationExecutor.CS and TaskOrchestrationContext.CS.In particular, see TaskOrchestrationExecutor.cs and TaskOrchestrationContext.cs.

Дополнительная информацияNext steps