Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Внешние события позволяют запущенным оркестрациям получать сигналы от внешних источников, таких как человеческие утверждения, обратные вызовы веб-перехватчиков или другие системы. В этой статье показано, как ждать, отправлять и обрабатывать внешние события в устойчивых оркестрациях.
Tip
Хотите отправить события в оркестрацию? Перейти к отправке событий.
Это важно
Поддержка будет завершена для внутрипроцессной модели 10 ноября 2026 г. Мы настоятельно рекомендуем перенести ваши приложения на изолированную модель рабочих процессов для полной поддержки.
Функции Оркестратора могут ожидать и прослушивать внешние события. Эта функция Устойчивые функции часто полезна для обработки взаимодействия с человеком или других внешних триггеров.
Замечание
Внешние события — это односторонняя асинхронная операция. Они не подходят для ситуаций, когда клиент, отправляющий событие, нуждается в синхронном ответе от функции оркестратора.
Оркестрации могут ждать и прослушивать внешние события. Эта функция часто полезна для обработки взаимодействия с человеком или других внешних триггеров.
Замечание
Внешние события — это односторонняя асинхронная операция. Они не подходят для случаев, когда клиент, отправляющий событие, нуждается в синхронном отклике от оркестрации.
Это важно
В настоящее время пакет SDK для устойчивых задач PowerShell недоступен.
Ожидание внешних событий
API "wait-for-external-event" для привязки триггера оркестрации позволяет функции оркестратора асинхронно ожидать и отслеживать событие, доставленное внешним клиентом. Функция оркестратора прослушивания объявляет имя события и форму получаемых данных .
API wait-for-external-event позволяет оркестрации асинхронно ожидать и прослушивать событие, доставленное внешним клиентом. Прослушивающая оркестрация объявляет имя события и структуру данных, которые она ожидает получить.
Изолированная рабочая модель
using Microsoft.Azure.Functions.Worker;
using Microsoft.DurableTask;
using Microsoft.Extensions.Logging;
public class BudgetApproval
{
private readonly ILogger _logger;
public BudgetApproval(ILoggerFactory loggerFactory)
{
_logger = loggerFactory.CreateLogger<BudgetApproval>();
}
[Function("BudgetApproval")]
public async Task Run(
[OrchestrationTrigger] TaskOrchestrationContext context)
{
bool approved = await context.WaitForExternalEventAsync<bool>("Approval");
if (approved)
{
// approval granted - do the approved action
}
else
{
// approval denied - send a notification
}
}
}
Модель внутрипроцессного процесса
[FunctionName("BudgetApproval")]
public static async Task Run(
[OrchestrationTrigger] IDurableOrchestrationContext context)
{
bool approved = await context.WaitForExternalEvent<bool>("Approval");
if (approved)
{
// approval granted - do the approved action
}
else
{
// approval denied - send a notification
}
}
Замечание
Если вы используете Устойчивые функции 1.x, используйте DurableOrchestrationContext вместо IDurableOrchestrationContext. Дополнительные сведения см. в статье о версиях Устойчивые функции.
public class BudgetApproval : TaskOrchestrator<object?, bool>
{
public override async Task<bool> RunAsync(TaskOrchestrationContext context, object? input)
{
bool approved = await context.WaitForExternalEvent<bool>("Approval");
if (approved)
{
// approval granted - do the approved action
}
else
{
// approval denied - send a notification
}
return approved;
}
}
Предыдущий пример прослушивает одно конкретное событие и выполняет действия при его получении.
Вы можете прослушивать несколько событий одновременно, например в следующем примере, которое ожидает одного из трех возможных уведомлений о событиях.
Изолированная рабочая модель
[Function("Select")]
public async Task Run(
[OrchestrationTrigger] TaskOrchestrationContext context)
{
Task<float> event1 = context.WaitForExternalEventAsync<float>("Event1");
Task<bool> event2 = context.WaitForExternalEventAsync<bool>("Event2");
Task<int> event3 = context.WaitForExternalEventAsync<int>("Event3");
Task winner = await Task.WhenAny(event1, event2, event3);
if (winner == event1)
{
// ...
}
else if (winner == event2)
{
// ...
}
else if (winner == event3)
{
// ...
}
}
Модель внутрипроцессного процесса
[FunctionName("Select")]
public static async Task Run(
[OrchestrationTrigger] IDurableOrchestrationContext context)
{
var event1 = context.WaitForExternalEvent<float>("Event1");
var event2 = context.WaitForExternalEvent<bool>("Event2");
var event3 = context.WaitForExternalEvent<int>("Event3");
var winner = await Task.WhenAny(event1, event2, event3);
if (winner == event1)
{
// ...
}
else if (winner == event2)
{
// ...
}
else if (winner == event3)
{
// ...
}
}
Замечание
Использование Устойчивые функции 1.x? Замените DurableOrchestrationContext на IDurableOrchestrationContext. Дополнительные сведения о других различиях версий см. в статье Устойчивые функции.
public class SelectOrchestrator : TaskOrchestrator<object?, object?>
{
public override async Task<object?> RunAsync(TaskOrchestrationContext context, object? input)
{
Task<float> event1 = context.WaitForExternalEvent<float>("Event1");
Task<bool> event2 = context.WaitForExternalEvent<bool>("Event2");
Task<int> event3 = context.WaitForExternalEvent<int>("Event3");
Task winner = await Task.WhenAny(event1, event2, event3);
if (winner == event1)
{
// ...
}
else if (winner == event2)
{
// ...
}
else if (winner == event3)
{
// ...
}
return null;
}
}
В предыдущем примере прослушивается любое из нескольких событий. Вы также можете ждать всех событий.
Изолированная рабочая модель
[Function("NewBuildingPermit")]
public async Task Run(
[OrchestrationTrigger] TaskOrchestrationContext context)
{
string applicationId = context.GetInput<string>();
Task gate1 = context.WaitForExternalEventAsync<object>("CityPlanningApproval");
Task gate2 = context.WaitForExternalEventAsync<object>("FireDeptApproval");
Task gate3 = context.WaitForExternalEventAsync<object>("BuildingDeptApproval");
// all three departments must grant approval before a permit can be issued
await Task.WhenAll(gate1, gate2, gate3);
await context.CallActivityAsync("IssueBuildingPermit", applicationId);
}
Модель внутрипроцессного процесса
[FunctionName("NewBuildingPermit")]
public static async Task Run(
[OrchestrationTrigger] IDurableOrchestrationContext context)
{
string applicationId = context.GetInput<string>();
var gate1 = context.WaitForExternalEvent("CityPlanningApproval");
var gate2 = context.WaitForExternalEvent("FireDeptApproval");
var gate3 = context.WaitForExternalEvent("BuildingDeptApproval");
// all three departments must grant approval before a permit can be issued
await Task.WhenAll(gate1, gate2, gate3);
await context.CallActivityAsync("IssueBuildingPermit", applicationId);
}
Замечание
Если вы используете Устойчивые функции 1.x, используйте DurableOrchestrationContext вместо IDurableOrchestrationContext. Перейдите к Устойчивые функции версии для полного описания различий версий.
В .NET, если полезные данные события не могут быть преобразованы в ожидаемый тип T, выбрасывается исключение.
public class NewBuildingPermit : TaskOrchestrator<string, object?>
{
public override async Task<object?> RunAsync(TaskOrchestrationContext context, string applicationId)
{
Task<object?> gate1 = context.WaitForExternalEvent<object?>("CityPlanningApproval");
Task<object?> gate2 = context.WaitForExternalEvent<object?>("FireDeptApproval");
Task<object?> gate3 = context.WaitForExternalEvent<object?>("BuildingDeptApproval");
// all three departments must grant approval before a permit can be issued
await Task.WhenAll(gate1, gate2, gate3);
await context.CallActivityAsync("IssueBuildingPermit", applicationId);
return null;
}
}
В .NET, если полезные данные события не могут быть преобразованы в ожидаемый тип T, выбрасывается исключение.
API "wait-for-external-event" ожидает неограниченное время для некоторых входных данных. Вы можете безопасно выгрузить функциональное приложение во время ожидания. Если и когда событие поступает для этого экземпляра оркестрации, экземпляр просыпается автоматически и немедленно обрабатывает событие.
Замечание
Если приложение-функция использует тарифный план 'По потреблению', плата не взимается, пока функция оркестратора ожидает внешнего события, независимо от времени ожидания.
Как и в случае с функциями действий, внешние события имеют по крайней мере однократную гарантию доставки. Это означает, что при определенных условиях (например, перезапуски, масштабирование, сбои и т. д.) приложение может получать дубликаты одного и того же внешнего события. Поэтому мы рекомендуем, чтобы внешние события содержали идентификатор, который позволяет вручную устранять дубликаты в системах оркестрации.
API "wait-for-external-event" ожидает неограниченное время для некоторых входных данных. Вы можете безопасно остановить процесс во время ожидания. Если и когда событие поступает для этого экземпляра оркестрации, оно просыпается автоматически и немедленно обрабатывает событие.
Внешние события имеют гарантию доставки хотя бы один раз. Это означает, что при определенных условиях (например, перезапуски, масштабирование, сбои и т. д.) приложение может получать дубликаты одного и того же внешнего события. Поэтому мы рекомендуем, чтобы внешние события содержали какой-то идентификатор, который позволяет вручную удалять дубликаты в оркестрациях.
Отправка событий
API raise-event, определенный привязкой клиента оркестровки, можно использовать для отправки внешнего события в оркестровку. Для отправки внешнего события в оркестрацию можно также использовать встроенный HTTP API для генерации события.
Инициированное событие включает instanceID, eventName, и eventData в качестве параметров. Функции оркестратора обрабатывают эти события с помощью wait-for-external-event API. Для того чтобы событие было обработано, eventName должен совпадать как на отправляющей, так и на принимающей стороне. Данные события также должны быть сериализуемыми в формате JSON.
Внутри системы механизмы "raise-event" поставляют в очередь сообщение, которое извлекается ожидающей функцией оркестратора. Если экземпляр не ожидает указанного имени события, сообщение о событии добавляется в очередь в памяти. Если экземпляр оркестрации позже начинает прослушивать это имя события, он проверяет очередь сообщений о событиях.
Замечание
Если экземпляр оркестрации с указанным идентификатором экземпляра отсутствует, сообщение о событии удаляется.
Ниже приведен пример функции с активацией очереди, которая отправляет событие "Утверждение" в экземпляр функции оркестратора. Идентификатор экземпляра оркестрации поступает из текста сообщения очереди.
API "raise-event" можно использовать в клиенте Durable Task для отправки внешнего события в оркестрацию.
Вызванное событие включает идентификатор экземпляра, имя события и данные события в качестве параметров. Оркестрации обрабатывают эти события с помощью API wait-for-external-event . Имя события должно совпадать как с отправкой, так и с получением, чтобы событие было обработано. Данные события также должны быть сериализуемыми в формате JSON.
Внутри системы механизмы "raise-event" помещают сообщение в очередь, которое затем обрабатывается ожидающей оркестрацией. Если экземпляр не ожидает указанного названия события, сообщение о событии добавляется в очередь в памяти. Если экземпляр оркестрации позже начинает прослушивать это имя события, он проверит очередь сообщений о событиях.
Замечание
Если в указанном instanceIDэкземпляре оркестрации нет, сообщение о событии удаляется.
Ниже приведен пример, который отправляет событие "Утверждение" в экземпляр оркестрации.
Изолированная рабочая модель
using Microsoft.Azure.Functions.Worker;
using Microsoft.DurableTask.Client;
public class ApprovalQueueProcessor
{
[Function("ApprovalQueueProcessor")]
public async Task Run(
[QueueTrigger("approval-queue")] string instanceId,
[DurableClient] DurableTaskClient client)
{
await client.RaiseEventAsync(instanceId, "Approval", true);
}
}
Модель внутрипроцессного процесса
[FunctionName("ApprovalQueueProcessor")]
public static async Task Run(
[QueueTrigger("approval-queue")] string instanceId,
[DurableClient] IDurableOrchestrationClient client)
{
await client.RaiseEventAsync(instanceId, "Approval", true);
}
Замечание
Для Устойчивые функции 1.x используйте вместо него атрибут OrchestrationClient и тип параметра DurableOrchestrationClient. Ознакомьтесь со статьёй о версиях Устойчивые функции для всех изменений, специфичных для каждой версии.
await client.RaiseEventAsync(instanceId, "Approval", true);
Во внутреннем режиме API "raise-event" помещает в очередь сообщение, которое извлекается ожидающей оркестрацией. Если экземпляр не ожидает указанного имени события, сообщение события добавляется в буфер в памяти. Если экземпляр оркестрации позже начинает прослушивать данное имя события, он проверит буфер на сообщения о событиях и активирует задачу, ожидающую его.
Замечание
Если экземпляр оркестрации с указанным идентификатором экземпляра отсутствует, сообщение о событии удаляется.
HTTP
Ниже приведен пример HTTP-запроса, который вызывает Approval событие для экземпляра оркестрации.
POST /runtime/webhooks/durabletask/instances/MyInstanceId/raiseEvent/Approval&code=XXX
Content-Type: application/json
"true"
В этом случае идентификатор экземпляра жестко закодирован как MyInstanceId.
Лучшие практики
При работе с внешними событиями следует учитывать следующие рекомендации.
Использование уникальных имен событий для дедупликации
Внешние события имеют гарантию доставки хотя бы один раз. В некоторых редких условиях (которые могут возникать во время перезапуска, масштабирования или сбоя), приложение может получать дубликаты одного и того же внешнего события. Рекомендуется, чтобы внешние события содержали уникальный идентификатор, который позволяет выполнять дедупликацию вручную в оркестраторах.
Замечание
Поставщик хранилища MSSQL использует внешние события и транзакционно обновляет состояние оркестратора, поэтому, в отличие от поставщика служба хранилища Azure, отсутствует риск дублированных событий. Однако по-прежнему рекомендуется, чтобы внешние события имели уникальные имена, чтобы код был переносимым между бэкендами.
Используйте таймауты, чтобы избежать бесконечных ожиданий
По умолчанию API ожидает неопределённое время. В большинстве реальных сценариев, таких как утверждения от человека, вы должны сопоставить устойчивый таймер с внешним событием, чтобы оркестрация могла принять меры (эскалация, отклонение, повтор), если событие не поступает до истечения крайнего срока.
Полное пошаговое руководство по примерам кода см. в разделе " Взаимодействие с человеком" и время ожидания.