Pull to refresh

Comments 25

Hangfire плох тем, что минимальный интервал минута там, в остальном больше всех понравился. В итоге пользуюсь Quartz.NET, но панель нужно ставить отдельно(CrystalQuartz ), да и она просто отвратительна. К тому же стоит учесть, что с CrystalQuartz нужен первый толчок, так как запускаются все задачи уже иначе.
Да. Панель CrystalQuartz не внушает восхищения. Но это лучше чем ничего. Чтоб добавить панель я установил Nuget пакет для OWIN. Добавил несколько строк в Startup.cs

      public void Configuration(IAppBuilder app)
        {
///....
            ISchedulerFactory schedulerFactory = new StdSchedulerFactory();
            IScheduler scheduler = schedulerFactory.GetScheduler();

            app.UseCrystalQuartz(scheduler);
        }   


И все заработало — по ссылке /quartz открылась панель, которая показывает запущенные задачи.
с hangfire имел только положительный опыт, в quartz однажды использовал неверное cron выражение, которое записалось в базу и потом джоб начинал одновременно выполняться сразу в нескольких потоках, что приводило к их созданию — непонятно, но результат — неверная работа программы и долгое выяснение причин
Да, кстати сравнительная таблица, пусть даже добавленная в перевод от себя, смотрелась бы отлично.
UFO just landed and posted this here

Масштабируемость, отказоустойчивость, персистентность?

Недавно тоже озадачивался темой запуска фоновых процесс, в контексте организации очереди обработки.
Возможно я не понимаю как готовить Hangfire или Quartz, но ни один из них не позволяет нормальным образом организовать Circuit Breaker на случай аварий.
Hangfire не позволяет практически конфигурировать интервалы между попытками.
Есть Polly, который всё это умеет делать замечательно, но туда никак не вкрутишь адекватно персистентность, он не про это.
Hangfire не позволяет переопределять названия таблиц в БД, так что использовать придется отдельные БД на каждое приложение, либо разделять их по схеме (dbo и т.д.).
Quartz творит с БД какое-то непотребство, гора таблиц в 2000-like стиле.
В итоге — придется писать видимо свой инструмент.
Hangfire – отличное решение, но, вроде, сразу требует использования базы данных для хранения очереди задач. Да и не совсем там все бесплатно – есть и платная версия.

Вроде? Вы их не запускали, что ли, когда сравнивали?


Чтобы внести ясность: да, Hangfire-у для работы необходима БД на SQL Server. В этой базе хранится очередь, через нее же синхронизируются процессы, выполняющие задачи из очереди. Приятный бонус такого подхода — "из коробки" работает кластеризация, т.е. распараллеливание процесссов-обработчиков. В платной версии хранилищем задач может выступать Redis, и есть ряд синтаксических вкусностей (прекрасно обходились и без них). Код бесплатной версии открыт, и репозиторий уже становится популярнее Квартца, хотя Hangfire на много лет моложе.

В первую очередь я искал то, что поможет мне решить мою конкретную задачу. И сделал перевод статьи. Поэтому не совсем корректно говорить, что я сам делал сравнение. Конечно, я сам попробовал запустить все варианты. Посмотрел исходники, чтоб оценить, что конкретно мне будет полезно. Честно говоря, до этого с Redis не сталкивался, хотя видел его поддержку, например, в Azure.
Судя по документации
SQL Server and Redis support
Hangfire uses persistent storage to store jobs, queues and statistics and let them survive application restarts. The storage subsystem is abstracted enough to support both classic SQL Server and fast Redis.

SQL Server provides simplified installation together with usual maintenance plans.
Redis provides awesome speed, especially comparing to SQL Server, but requires additional knowledge.

поддержка Redis есть в бесплатной версии.
Их реализация — платно.
Есть порт на базе StackExchange.Redis https://github.com/BoltR/Hangfire.Redis.StackExchange, который можно прикрутить к бесплатной версии.
Нет не необходима — он спокойно может все хранить в памяти. Конечно персистентность страдает, но для задача, которым это не нужно вполне подходит.

Ваша правда. Забыл, что к Hangfire все-таки можно прикрутить in-memory storage.

Подскажите, пожалуйста, по поводу in-memory storage.
Я нашел Hangfire.MemoryStorage.
Но в описании сказано, что использовать можно только для тестирования. А дальше: "… не может использоваться в production ..."
It can be useful for testing purpose like check the behaviour and use it in a development environment. Please note that it should not be used in production (no integrity and no thread safe even if many cases are managed).
Я это хранилище (Hangfire.MemoryStorage) использую для задачи периодического чтения очереди. Персистентость для этой задачи не важна, а какое-то хранилище быть все равно должно.
Я понимаю что это может быть оверкил, но я бы использовал Akka.Net.
Кинул актору задачу и не переживаешь что он завалится. CircuitBreaker, BackoffStrategy, Supervising из коробки.
Ну и до кучи персистентность, ремоутинг, кластеринг, и тут Остапа понесло…
Инструмент похоже и правда очень мощный, хотя очень забавно смотрится куча вставок в документации http://getakka.net/docs/Fault%20tolerance "!!!TODO: Port sample code" :)
Akka.Net — порт одноимённого фреймворка Akka из Scala-мира. Если я правильно понимаю портированием и коммерческой поддержкой занимается Petabridge. Поэтому функционал есть, а документация местами отсутствует. Но отсутствующую документацию по Akka.Net всегда можно найти в документации для Scala http://akka.io/docs/
Не ту ссылку дал. По Fault Tolerance документация здесь
Немного привыкнув к Scala код можно передирать почти 1:1, т.к. фреймворк полностью портирован.
Подскажете, пожалуйста, еще ссылку на прозрачное описание реализации персистентности заданий в Akka.Net? Пока насколько разобрался это http://getakka.net/docs/persistence/persistent-actors, но из описания следует как будто надо самому заботиться хранением данных по актору.
Прозрачное описание персистентности в Akka лежит в понимании EventSourcing.
Нужно сделать актора, который реагирует на команды. Изменение состояния происходит через генерацию и сохранении событий в хранилище. При восстановлении состояния читается поток событий и проигрывается заново реакция на них.

Персистентность руками делать не надо, просто подключаем плагин из готовых и работаем.
Если надо по-быстрому, то есть плагин для embedded SqLite.

Когда я "последний раз" искал что-то для фоновых заданий — брать большие комплексы типа Hangfire не хотелось из-за требования БД, а изощренные (извращенные) расписания для запуска типа "каждый понедельник в 8 утра, во вторник каждые 10 минут" с одной стороны были слишком заумными и нереальными, с другой стороны сразу же возникают опасения "что если при 10 минутном запуске задача будет выполнять 12 минут — запустится ли вторая не дожидаясь конца первой".


В итоге сделал свой велосипед RecurrentTasks — обычный Task просыпается, делает что надо и снова засыпает на заданный интервал. При этом для "сложных" задач, которые должны работать лишь "трижды в день" — все равно где-то в бизнес-требованиях есть "дата последнего запуска" той или иной функции — в итоге удобно оказалось сделать что таск стартует раз в 20-30 минут, считывает дату из реальной базы и "делает дело" только если надо. Заодно этим решается проблема "если приложение было выключено в заданное время" — при следующем запуске все отработает. Периодом можно управлять прямо внутри основного метод: если очередь пустая то следующий раз читать ее "через минуту", если еще что-то есть — "через 10 секунд".

А что будет, если пул решит завершиться во время выполнения задания?

Начиная с ASP.Net Core 2.1 где появился IHostedService — дернется cancellation token, а дальше уж смотря как написан "полезный" код таска.

Sign up to leave a comment.

Articles