Как динамически планировать регулярные казни? - PullRequest
0 голосов
/ 02 октября 2019

Мне нужно периодически выполнять некоторые расчеты на веб-сайте. Сложность в том, что они не работают с регулярными интервалами, так как конечные пользователи планируют запускать их каждые N минут (их можно изменить в любое время), а затем приостановят работу к концу рабочего дня и возобновят работу. снова на следующее утро или после выходных. Конечные пользователи могут даже указать дни, когда он вообще не будет работать. В принципе, я не могу использовать фиксированное расписание.

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

До сих пор я выполнял это как веб-задание, вращающееся несколько Task (по одному на график расчета) и ожидая (неограниченно) для всех из них: await Task.WhenAll(calculationTasks);

Каждая задача состоит из цикла while (true) {, где I:

  1. Выполните фактический расчет
  2. Определите, когда следующий расчет должен быть
  3. Приостановить выполнение потока Thread.Sleep() на соответствующее количество миллисекунд: как я уже говорил выше, это может быть от парыот нескольких минут до нескольких дней.

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

Кто-нибудь из вас сталкивался с подобной проблемой? Какова будет наилучшая реализация / подход для такого типа динамического планирования задач?

1 Ответ

0 голосов
/ 06 октября 2019

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

Вы должны запустить одну функцию для каждого задания и использовать C # скрипт (файлы .csx) для поддержания функций динамическими. Работа заключается в управлении сценариями функций.

Вот как я бы преобразовал ваш проект. Не стесняйтесь заимствовать, редактировать или делать это по-своему:

  1. Чтобы упростить создание обновлений, я бы взял логику ваших вычислений и превратил их в библиотеку классов внутри * 1012. * папку или преобразовать их в файлы .csx и добавить их в папку ./shared в папке wwwroot. После этого вы сможете использовать его в функциях, не дублируя его, используя #load "..\shared\calculation1Logic.csx" в верхней части файла .csx функции. Это необязательно

Итак, теперь мы имеем:- wwwroot|- веб-сайт (если вы используете тот же сервис приложений)|- общий||- analysis1Logic.csx||- analysis2Logic.csx

или

|бункер||calculationLogic.dll


Создайте несколько шаблонов функций, которые обернут каждый из этих вычислений.

analysis1Function.csx пример

#load "..\shared\calculation1Logic.csx"

using Microsoft.Extensions.Logging;

public static void Run(TimerInfo myTimer, ILogger log)
{
    log.LogInformation($"running calculation 1: {DateTime.Now}");
    calculation1Logic(myTimer, log);
}

Чтобы создать новое задание, я бы использовал конечную точку createfunction в API управления Azure и передал ей этот шаблон и привязку таймера с расписанием, преобразованным в синтаксис CRON. Так как из примера это гораздо проще создать, есть один в этом потоке MSDN. Он находится в Node, но поскольку я использую .csx вместо предварительно скомпилированного кода, будет работать тот же метод динамического добавления функций. Убедитесь, что имена функций уникальны, и сохраните их, чтобы позже их можно было редактировать или удалять.

Теперь у меня есть файлы, основанные на том, как они будут преобразованы из запроса API:- wwwroot|- веб-сайт (если вы используете тот же сервис приложений)|- общий||- analysis1Logic.csx||- analysis2Logic.csx|- User1_Calculation1||- run.csx||- function.json||- function.proj|- User2_Calculation2||- run.csx||- function.json||- function.proj|- host.json (часть времени выполнения функций вместе с extensions.csproj)|- extensions.csproj|- бен


Редактирование расписания. Это где это становится немного сложнее. Есть несколько способов сделать это. Самым безопасным является удаление и повторное добавление функции каждый раз. Другой - заменить function.json на обновленную привязку. Этот способ немного выходит за рамки того, что вы «должны» сделать, но он допускает динамические повторные привязки. function.json - это простой файл, если у вас есть только одна привязка, поэтому вы должны иметь возможность генерировать его программно.

function.json пример

{
  "bindings": [
    {
      "name": "myTimer",
      "type": "timerTrigger",
      "direction": "in",
      "schedule": "0 */5 * * * *"
    }
  ]
}

Вы можете заменить файлы в службе приложений без полного развертывания, получив доступ к файлам по FTP. Теперь, поскольку изменение файла по FTP не уведомляет хост-процесс о том, что для его реализации требуется новое расписание, вам необходимо отправить запрос на /syncfunctiontriggers через API управления чтобы обновить его. Это не перезапускает полное приложение, но если вы часто меняете расписание, вы можете захотеть, чтобы этот вызов API выполнялся по таймеру - каждую минуту или любой другой интервал, который вам больше подходит.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...