Cloud & IT Cert Prep · Урок

Durable Functions для рабочих процессов с состоянием

Оркестрируйте длительные рабочие процессы с помощью шаблонов оркестратора Durable Functions (разветвление и объединение, цепочка, мониторинг) и разберитесь, как фиксируются контрольные точки состояния.

Урок 2 из 413 шагов

«Durable Functions для рабочих процессов с состоянием» — бесплатный урок Cloud & IT Cert Prep на CoddyKit. Это урок 2 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Cloud & IT Cert Prep, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Cloud & IT Cert Prep содержит 4 уроков всего.

Зачем нужны Durable-функции

Обычные функции Azure не сохраняют состояние: каждый вызов выполняется независимо и не имеет сведений о предыдущих вызовах. Durable-функции расширяют возможности функций Azure, позволяя писать рабочие процессы с сохранением состояния и длительным выполнением с помощью обычного кода async/await. Durable Task Framework автоматически сохраняет контрольную точку состояния в Azure Storage после каждого шага, поэтому рабочие процессы могут пережить перезапуск сервера, истечение времени ожидания или плановое обслуживание и продолжить выполнение точно с того места, на котором остановились.

Три типа функций

Durable-функции поддерживают три типа функций. Функция-оркестратор координирует весь рабочий процесс: она вызывает функции действий и ожидает результаты с помощью yield или await, фактически не блокируя поток. Функция действия выполняет одну отдельную операцию (вызывает API, записывает данные в базу данных) и является единственным местом, где должны выполняться побочные эффекты. Функция-сущность сохраняет небольшие фрагменты долговременного состояния (счётчики, флаги) между вызовами.

// Client function (HTTP trigger) — starts the orchestration
module.exports = async function (context, req) {
  const client = df.getClient(context);
  const orderId = req.body.orderId;
  const instanceId = await client.startNew('OrderOrchestrator', undefined, { orderId });
  return client.createCheckStatusResponse(context.bindingData.req, instanceId);
};

Шаблон цепочки

Шаблон цепочки запускает функции действий последовательно, передавая результат одной функции в качестве входных данных следующей. Оркестратор ожидает завершения каждого действия по очереди. Если какое-либо действие завершается с ошибкой, рабочий процесс останавливается, и его можно перезапустить с шага, на котором произошла ошибка. Это самый простой шаблон Durable-функций, подходящий для рабочих процессов, в которых каждый шаг зависит от результата предыдущего, например для конвейеров обработки заказов.

// Orchestrator: chaining pattern
const df = require('durable-functions');
module.exports = df.orchestrator(function* (context) {
  const orderId = context.df.getInput().orderId;

  const validated = yield context.df.callActivity('ValidateOrder', orderId);
  const charged   = yield context.df.callActivity('ChargePayment', validated);
  const shipped   = yield context.df.callActivity('ShipOrder', charged);

  return { status: 'shipped', trackingId: shipped.trackingId };
});

Шаблон распределения и сбора

Шаблон распределения и сбора запускает несколько функций действий параллельно и ожидает завершения всех них, прежде чем продолжить выполнение. Оркестратор одновременно запускает все задачи с помощью callActivity, не дожидаясь их завершения, собирает объекты задач в массив, а затем ожидает результат Task.all(). Для независимых рабочих элементов, таких как обработка нескольких файлов, вызов нескольких API или пакетные операции, этот подход значительно быстрее последовательной обработки.

// Orchestrator: fan-out / fan-in
module.exports = df.orchestrator(function* (context) {
  const items = context.df.getInput().items;

  // Fan-out: start all tasks in parallel
  const tasks = items.map(item => context.df.callActivity('ProcessItem', item));

  // Fan-in: wait for all tasks to complete
  const results = yield context.df.Task.all(tasks);

  return results;
});

Шаблон мониторинга

Шаблон мониторинга через определённые интервалы опрашивает внешнюю систему, пока не будет выполнено условие. Это похоже на цикл опроса, но полностью поддерживает сохранение состояния. Оркестратор вызывает действие для проверки состояния, ожидает настраиваемый интервал с помощью createTimer, а затем повторяет цикл. Поскольку между опросами состояние сохраняется в хранилище, оркестратор не расходует вычислительные ресурсы во время ожидания, что делает этот подход гораздо эффективнее таймера, который просто бездействует.

// Orchestrator: monitor pattern (poll until job completes)
module.exports = df.orchestrator(function* (context) {
  const jobId = context.df.getInput().jobId;
  const expiry = new Date(context.df.currentUtcDateTime);
  expiry.setHours(expiry.getHours() + 24); // 24-hour timeout

  while (context.df.currentUtcDateTime < expiry) {
    const status = yield context.df.callActivity('GetJobStatus', jobId);
    if (status === 'completed') return { jobId, status };
    if (status === 'failed') throw new Error('Job failed');
    // Wait 30 seconds before next poll
    const nextCheck = new Date(context.df.currentUtcDateTime);
    nextCheck.setSeconds(nextCheck.getSeconds() + 30);
    yield context.df.createTimer(nextCheck);
  }
  throw new Error('Workflow timed out');
});

Шаблон взаимодействия с пользователем

Шаблон взаимодействия с пользователем приостанавливает оркестрацию и ожидает внешнее событие, например одобрение руководителя. Оркестратор ожидает результат waitForExternalEvent, который может поступить через несколько дней или недель без расходования вычислительных ресурсов. Внешняя система (ссылка для одобрения по электронной почте, мобильное приложение, веб-перехватчик) вызывает HTTP API Durable-функций, чтобы инициировать событие и разблокировать оркестрацию. Для автоматического истечения времени ожидания и эскалации, если ответ не поступил, этот шаблон можно объединить с таймером.

// Orchestrator: wait for human approval with timeout
module.exports = df.orchestrator(function* (context) {
  const request = context.df.getInput();

  yield context.df.callActivity('SendApprovalEmail', request);

  const timeout = df.Task.createTimer(context, new Date(Date.now() + 48 * 3600 * 1000));
  const approval = context.df.waitForExternalEvent('ApprovalResponse');

  const winner = yield context.df.Task.any([approval, timeout]);

  if (winner === approval) {
    const approved = winner.result;
    return approved ? 'Approved' : 'Rejected';
  } else {
    return 'Timed out — escalated';
  }
});

Ограничения оркестратора

Для функций-оркестраторов действуют важные ограничения, поскольку для восстановления состояния они могут многократно воспроизводиться по журналу истории. Они должны быть детерминированными: не используйте Date.now() и Math.random() и не выполняйте прямые операции ввода-вывода. Вместо этого используйте context.df.currentUtcDateTime для получения меток времени, а все операции ввода-вывода выполняйте через функции действий. Ведение журнала в теле оркестратора при повторном воспроизведении создаст дублирующиеся записи; вместо этого используйте функции действий для ведения журнала.

// WRONG — non-deterministic, will cause replay bugs
module.exports = df.orchestrator(function* (context) {
  const now = new Date();          // Don't use Date()
  const rand = Math.random();       // Don't use Math.random()
  const data = await fetch('/api'); // Don't make HTTP calls directly
});

// CORRECT
module.exports = df.orchestrator(function* (context) {
  const now = context.df.currentUtcDateTime; // OK
  const data = yield context.df.callActivity('FetchData', null); // OK
});

Управление экземплярами: состояние и завершение

Каждый запуск оркестрации имеет уникальный идентификатор экземпляра, который можно использовать для запроса его состояния, отправки событий или завершения. HTTP API управления Durable-функциями предоставляет конечные точки для проверки состояния (GET /instances/{id}), отправки событий (POST /instances/{id}/raiseEvent/{name}) и завершения (POST /instances/{id}/terminate). Используйте привязку клиента Durable в своих функциях, чтобы программно обращаться к этим операциям.

// Client function: check orchestration status
module.exports = async function (context, req) {
  const client = df.getClient(context);
  const instanceId = req.params.instanceId;

  const status = await client.getStatus(instanceId, true, true, true);
  return {
    status: 200,
    body: {
      instanceId,
      runtimeStatus: status.runtimeStatus,
      customStatus: status.customStatus,
      output: status.output
    }
  };
};

Хранилище и производительность

Durable-функции хранят историю оркестрации, состояние экземпляров и очереди сообщений между функциями в учётной записи Azure Storage (либо используют Azure SQL или хранилище Netherite для более высокой пропускной способности). Каждая контрольная точка записывается в Azure Table Storage и Azure Queue Storage. В сценариях с высокой пропускной способностью (при тысячах одновременно выполняющихся оркестраций) хранилище Netherite использует Azure Event Hubs для значительно более высокой производительности. Следите за глубиной очереди оркестрации, чтобы выявлять узкие места.

// host.json: configure the Durable Task storage provider
{
  'version': '2.0',
  'extensions': {
    'durableTask': {
      'hubName': 'MyTaskHub',
      'storageProvider': {
        'type': 'azure',
        'connectionStringName': 'AzureWebJobsStorage',
        'controlQueueBatchSize': 32,
        'maxQueuePollingInterval': '00:00:02'
      }
    }
  }
}

Обработка ошибок и повторные попытки

Функции действий могут создавать исключения, которые передаются обратно оркестратору как TaskFailedException. Используйте блоки try-catch в оркестраторе, чтобы корректно обрабатывать сбои. Для временных ошибок настройте автоматические повторные попытки с увеличением интервала с помощью callActivityWithRetry, указав максимальное число попыток, интервал перед первой повторной попыткой и коэффициент увеличения интервала. Это рекомендуемый шаблон для действий, вызывающих внешние API или базы данных.

// Orchestrator: retry an activity with exponential backoff
module.exports = df.orchestrator(function* (context) {
  const retryOptions = new df.RetryOptions(
    5000,  // firstRetryIntervalInMilliseconds
    3      // maxNumberOfAttempts
  );
  retryOptions.backoffCoefficient = 2; // 5s, 10s, 20s

  try {
    const result = yield context.df.callActivityWithRetry(
      'CallExternalAPI',
      retryOptions,
      context.df.getInput()
    );
    return result;
  } catch (e) {
    yield context.df.callActivity('SendFailureAlert', e.message);
    throw e;
  }
});

Durable-сущности

Durable-сущности (функции-сущности) реализуют небольшие фрагменты долговременного состояния, доступные по идентификатору, подобно виртуальным акторам. У сущности есть идентификатор и состояние, сохраняющееся между вызовами. Вы вызываете операции сущности из оркестратора или клиента, а сущность обрабатывает их по одной за раз (последовательно). Распространённые варианты применения — счётчики, конечные автоматы состояния одобрения, ограничители частоты и корзины покупок: любые сценарии, где требуется долговременное изменяемое состояние без базы данных.

// Counter entity function
const df = require('durable-functions');
module.exports = df.entity(function (context) {
  let count = context.df.getState(() => 0);
  const operation = context.df.operationName;

  if (operation === 'add') count += context.df.getInput();
  if (operation === 'reset') count = 0;
  if (operation === 'get') context.df.return(count);

  context.df.setState(count);
});

// From orchestrator, increment counter entity
// const entityId = new df.EntityId('Counter', 'myCounter');
// yield context.df.callEntity(entityId, 'add', 1);

Быстрая проверка

Проверьте своё понимание концепций Microsoft Azure Fundamentals (AZ-900), рассмотренных в этом уроке.

Повторение урока

В этом уроке Вы узнали, что Durable-функции поддерживают рабочие процессы с сохранением состояния и длительным выполнением, сохраняя состояние оркестратора в Azure Storage с помощью контрольных точек; к основным шаблонам относятся цепочка, распределение и сбор, мониторинг и взаимодействие с пользователем; оркестраторы должны быть детерминированными, а все операции ввода-вывода и недетерминированные вызовы должны выполняться через функции действий. Далее мы рассмотрим Azure Logic Apps.

Можно начать бесплатно

Изучай Cloud & IT Cert Prep с ИИ-репетитором — бесплатно

Пиши и запускай код прямо в браузере, получай мгновенную помощь от ИИ-репетитора 24/7 и продолжи учиться на сайте или в приложении.

Курсы
150
Уроки
600

Часто задаваемые вопросы

Урок «Durable Functions для рабочих процессов с состоянием» бесплатный?

Да — полный текст урока «Durable Functions для рабочих процессов с состоянием» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Cloud & IT Cert Prep, подпишись на CoddyKit PRO. Курс Cloud & IT Cert Prep содержит 4 уроков всего.

Чему я научусь в уроке «Durable Functions для рабочих процессов с состоянием»?

Оркестрируйте длительные рабочие процессы с помощью шаблонов оркестратора Durable Functions (разветвление и объединение, цепочка, мониторинг) и разберитесь, как фиксируются контрольные точки состояни… Ты практикуешь Cloud & IT Cert Prep с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.

Нужен ли мне опыт, чтобы начать Cloud & IT Cert Prep?

Предыдущий опыт не требуется. Cloud & IT Cert Prep на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 2 из 4.

Сколько времени занимает урок «Durable Functions для рабочих процессов с состоянием»?

Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.

Можно ли писать и запускать код в этом уроке Cloud & IT Cert Prep?

Да. Каждый урок Cloud & IT Cert Prep включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.

Все уроки этого курса

  1. Триггеры и привязки Azure Functions
  2. Durable Functions для рабочих процессов с состоянием
  3. Azure Logic Apps
  4. Event Grid и событийная архитектура
← Назад к Cloud & IT Cert Prep