Следуйте за мной в Twitter, с радостью приму ваши предложения по темам или улучшениям / Крис

Устойчивые функции - это расширение функций Azure, которое позволяет писать функции с отслеживанием состояния в бессерверной среде. Функции Durable управляют state, checkpoints и restarts за вас.

Что это вообще значит, спросите вы?

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

Как насчет этого. Представьте, что у вас есть ситуация, когда
вам нужно управлять чем-то, разделив это на разные контрольные точки. Каждая контрольная точка на один шаг ближе, чтобы считаться обработанной. Более конкретно представьте себе игру, например, в которой вам нужно загрузить кучу различных ресурсов, и только когда все загружено и готово, вы можете играть в игру.

Ну ладно, это похоже на платформу рабочего процесса

Да, именно это позволяет вам указать, как что-то должно выполняться в потоке. Существуют даже разные архитектурные шаблоны, рекомендуемые для разных потоков.

Похоже, это может быть дорого, не так ли?

Нет, на самом деле, модель оплаты очень близка к той, которую используют функции Azure, платите только тогда, когда функции / рабочий процесс фактически выполняются.

Отлично, расскажите подробнее

В этой статье мы рассмотрим:

  • Что такое функции Durable, давайте поговорим о том, что это такое и каковы основные концепции
  • Как это работает, мы немного объясним, как это работает
  • Ресурсы, мы предоставим вам некоторые ресурсы, чтобы вы могли глубже изучить
  • Лаборатория, мы будем кодировать пример, чтобы вы увидели основные используемые концепции и что происходит, когда

Концепции и объяснение высокого уровня

При работе с долговечными функциями нам необходимо знать несколько концепций. Все концепции играют роль, которая вместе позволяет нам выполнять нашу долговечную функцию.

  • Функция оркестратора - это функция, с помощью которой мы определяем рабочий процесс, мы настраиваем, что должно происходить в рабочем процессе, какие действия выполнять и что происходит, когда они будут выполнены.
  • Функция действия, функции действия - это основная единица работы в устойчивой оркестровке функций. Функции деятельности - это функции и задачи, которые организуются в процессе. Вы можете иметь столько функций активности, сколько захотите. Обязательно дайте им описательные имена, которые представляют шаги в вашем потоке.
  • Клиентские функции. Клиентские функции - это запускаемые функции, которые создают новые экземпляры оркестровки. Клиентские функции - это точка входа для создания экземпляра оркестровки устойчивых функций.

Хорошо, я думаю, что понял, но не могли бы вы объяснить это поподробнее?

Конечно, лучший способ объяснить это - на реалистичном примере и изображении. Итак, давайте поговорим об обработке заказов. В обработке заказов мы предполагаем, что нам нужно выполнить следующие задачи:

Учитывая, что мы знаем, как обрабатывается заказ, давайте покажем вам это изображение, чтобы вы получили представление о рабочем процессе:

Хорошо, выше мы видим, как вызывается клиентская функция. В случае создания заказа это обычно конечная точка HTTP, с которой мы сталкиваемся из приложения. Следующее, что должно произойти, - это то, что клиентская функция запускает экземпляр оркестровки. Это означает, что мы получим instance id, нашу уникальную ссылку на этот конкретный поток. Следующее, что должно произойти, - это то, что мы попытаемся выполнить все внутри оркестровки, например checking the inventory, charging the customer и creating a shipment.

Как это работает

Давайте поговорим подробнее о том, как это работает технически. Проблема с оркестровкой в ​​том, что то, что она оркестрирует, обычно асинхронно, что означает, что мы не знаем точно, когда что-то заканчивается. Чтобы не платить за него текущие расходы, долговечные функции отключаются и сохраняют состояние.

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

подождите, перезапустить все?

Не беспокойтесь, во время воспроизведения, если код пытается вызвать функцию (или выполнить любую другую асинхронную работу), Durable Task Framework обращается к истории выполнения текущей оркестровки. Если он обнаруживает, что функция действия уже выполнилась и дала результат, он воспроизводит результат этой функции, и код оркестратора продолжает выполняться.

О'кей, звучит лучше

Воспроизведение продолжается до тех пор, пока код функции не будет завершен, или пока не будет запланирована новая асинхронная работа.

Ресурсы

- Бесплатная учетная запись Azure. Вам нужно будет зарегистрироваться в Azure, чтобы использовать долговечные функции
- Создание вашей первой надежной функции с помощью JavaScript Краткое руководство, которое проведет вас через создание надежной функции
- Долговечные функции концепции Узнайте больше о концепциях и шаблонах, а также о том, как реализовать указанные шаблоны.
- [ Ограничения функций оркестратора ] Ограничения, о которых необходимо знать.

Лабораторная работа - простая последовательность действий

Мы считаем, что лучший способ учиться - это что-то строить с его помощью. Так как же нам это сделать? Все очень просто. Используя VS Code, мы можем установить плагин, который упростит этот процесс:

Создание нашего проекта

Откройте палитру команд или введите COMMAND + SHIFT + P.

Затем мы выбираем следующее, чтобы создать новый проект

Затем мы выбираем язык, например javascript. Затем мы сталкиваемся с этим списком вариантов:

Как вы можете видеть выше, мы выделили три варианта, потому что именно их мы будем использовать в этой лабораторной работе. Нам нужна точка входа Durable Functions HTTP Start, поэтому сначала выберем ее:

Затем давайте создадим нашу функцию оркестратора. Снова нажмите COMMAND + SHIFT + P, выберите Azure Functions: Create Function и выберите Durable Functions Orchestrator, дайте ему имя Orchestrator.

После этого вам будет предложено выбрать учетную запись хранения:

Вам нужно будет выбрать Subscription, Storage account и Resource group. Причина в том, что когда вы сохраняете состояние своей функции, его нужно где-то сохранить для последующего восстановления.

Мы почти закончили, осталось еще кое-что создать Activity function. Мы также можем создать это с помощью COMMAND+SHIFT+P, Azure Functions: Create Function и Durable functions activity, давайте дадим ему имя Hello, когда он запросит у нас имя.

Если вы следовали по тексту, это должно выглядеть так:

Объяснение артефактов

Итак, мы создали три разных артефакта: функцию orchestrator, функцию запуска / клиента HTTP и функцию активности. Как это все работает?

Ну, все начинается с HttpStart функции, которая все запускает. Затем указанная функция запускает Orchestrator, который, в свою очередь, запускает Activity functions, указанный в оркестраторе. Звучит немного теоретически, но давайте углубимся в каждый из этих артефактов и посмотрим, что происходит в коде.

HttpStart

Как упоминалось выше, это функция, с которой все начинается. Давайте посмотрим на его исходный код и обсудим, что происходит:

// HttpStart/index.js
const df = require("durable-functions");

module.exports = async function (context, req) {
    const client = df.getClient(context);
    const instanceId = await client.startNew(
      req.params.functionName, 
      undefined, req.body
    );

    context.log(`Started orchestration with ID = '${instanceId}'.`);

    return client.createCheckStatusResponse(
      context.bindingData.req, 
      instanceId
    );
};

Выше мы видим, что получаем ссылку на client, вызывая getClient в экземпляре устойчивых функций df, который мы импортируем из библиотеки durable-functions.
Затем наш client экземпляр вызывает startNew, который производит instanceId. instanceId - это ссылка или обработчик для вызова этой конкретной функции. Это не имеет большого значения для этой демонстрации, но для второй мы будем использовать эту информацию.
Последнее, что нужно сделать, - это создать HTTP-ответ.

Давайте посмотрим на function.json, наш файл конфигурации, в котором мы настраиваем входы и выходы для нашей функции:

// HttpStart/function.json
{
  "bindings": [
    {
      "authLevel": "function",
      "name": "req",
      "type": "httpTrigger",
      "direction": "in",
      "route": "orchestrators/{functionName}",
      "methods": [
        "post",
        "get"
      ]
    },
    {
      "name": "$return",
      "type": "http",
      "direction": "out"
    },
    {
      "name": "starter",
      "type": "orchestrationClient",
      "direction": "in"
    }
  ]
}

У нас есть две интересные информации. Во-первых, у нас есть httpTrigger, то есть мы можем достичь этой функции через HTTP-вызов, в частности, через маршрут с именем orchestrators/{functionName}. Другая интересная информация - это последняя запись с типом orchestrationClient. Это позволяет нам получить client ссылку в нашем коде, без нее мы бы не смогли. Поэтому не забудьте включить эту конфигурацию, если вам нужен экземпляр клиента.

Оркестратор

Давайте теперь посмотрим на Orchestrator. Здесь происходит все самое интересное, здесь мы настраиваем наш поток, какую функцию вызывать, когда и почему. Посмотрим на код:

// Orchestrator/index.js
const df = require("durable-functions");

module.exports = df.orchestrator(function* (context) {
    const outputs = [];

    // Replace "Hello" with the name of your Durable Activity Function.
    outputs.push(yield context.df.callActivity("Hello", "Tokyo"));
    outputs.push(yield context.df.callActivity("Hello", "Seattle"));
    outputs.push(yield context.df.callActivity("Hello", "London"));

    // returns ["Hello Tokyo!", "Hello Seattle!", "Hello London!"]
    return outputs;
});

Первым делом мы видим, что у нас есть метод orchestrator, который принимает функцию генератора.

Что такое генераторы?

Они очень похожи на async/await и позволяют выполнять асинхронный код синхронно. Вы узнаете их по тому, что они имеют * как часть объявления функции следующим образом:

function*() {}

а также что используется ключевое слово yield. yield используется так же, как await, и означает, что мы должны оставаться здесь и ждать в коде, пока наша асинхронная операция не завершится.

Итак, что это означает для нашего кода выше? Давайте посмотрим внимательнее:

outputs.push(yield context.df.callActivity("Hello", "Tokyo"));

Здесь мы видим, что мы вызываем context.df.callActivity() с аргументами Hello и Tokyo с ключевым словом yield. Это просто означает, что мы вызываем функцию действия Hello с аргументом Tokyo. Мы видим, что есть еще два вызова callActivity(), которые не будут выполнены, пока наша функция активности не завершится.

Привет

Далее у нас есть функция активности. Здесь мы выполняем всю тяжелую работу. Глядя на index.js для каталога Hello, мы видим следующий код:

module.exports = async function (context) {
    return `Hello ${context.bindings.name}!`;
};

Мы видим, что он сразу же возвращается, но это определенно может быть длительной деятельностью. Дело в том, выполняется ли это за миллисекунду или занимает какое-то время, это не имеет значения, функция оркестрации все равно должна дождаться ее завершения.

Отладка

Вам может казаться, что вы все поняли до этого момента, но это действительно важно, когда вы видите, что происходит процесс отладки. Вот что мы собираемся делать дальше: мы собираемся запустить нашу долговечную функцию из VS Code, и вы сможете увидеть, как и когда достигаются точки останова.

Первое, что нам нужно сделать, это установить библиотеку durable-functions NPM, о которой мы постоянно говорим, так что давайте сделаем это:

npm install durable-functions

Теперь мы готовы к отладке, поэтому давайте нажмем кнопку отладки.

В терминале должно быть напечатано что-то подобное.

Следующее, что нам нужно сделать, это запустить все, выбрав маршрут нашей клиентской функции, как указано выше orchestrators/{functionName}. Поскольку у нас есть только одна такая функция с именем Orchestrator, нам нужно запустить все это, вызвав следующий URL-адрес в браузере:

http://localhost:7071/api/orchestrators/Orchestrator

Первое, что должно произойти, - это наша HttpStart функция и ее index.js будут выполнены следующим образом:

Мы позволяем отладчику продвигаться вперед:

Выше мы видим, как попадает в Orchestrator и его index.js.

Затем мы переходим к следующей точке останова и видим, что следующей выполняется наша функция активности Hello и ее index.js.

Мы продвинули точку останова и снова оказались в функции оркестровки:

Это приведет к повторному обращению к функции activity, на этот раз с аргументом Seattle, например:

Как видите, это будет продолжаться между функцией активности и оркестратором, пока оркестратор не будет готов.

Давайте пройдемся по всем точкам останова.

В итоге мы попадаем на такую ​​страницу, которая является HTTP-ответом метода HttpStart.

На данный момент нам интересно узнать, что мы в итоге создали? Ответ кроется в URL-адресе statusQueryGetUri. Перейдем по этой ссылке:

Как вы можете видеть выше, ответ нашей функции Orchestration представляет собой массив, состоящий из ответов всех функций активности, например:

"output": [
  "Hello Tokyo!",
  "Hello Seattle!",
  "Hello London"
]

Так все закончилось из-за того, как мы построили код, мы написали это:

outputs.push(yield context.df.callActivity("Hello", "Tokyo"));
outputs.push(yield context.df.callActivity("Hello", "Seattle"));
outputs.push(yield context.df.callActivity("Hello", "London"));

// returns ["Hello Tokyo!", "Hello Seattle!", "Hello London!"]
return outputs;

Резюме

О долговечных функциях можно узнать гораздо больше, но я уже слышу, как некоторые из вас храпят на этом этапе, поэтому мы сохраним такие темы, как шаблоны приложений и реализация шаблона Fan-out/fan-in, для следующей части.

Так что я надеюсь, что вы в восторге от этого.

Благодарности

Я бы не стал писать это, если бы не ваше руководство в том, как работают долговечные функции. Вы оба замечательные люди.

- Энтони Чу]
dev.to,
twitter
- Джереми Ликнесс
dev.to
twitter

Так что дайте им подписаться, они действительно знают свое дело в бессерверном режиме.

Первоначально опубликовано на https://dev.to 3 июня 2019 г.