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

Этот пост не предназначен ни для обсуждения различий между Hangfire и родным .Net Core IHostedService (подробнее читайте в другом моем сообщении в блоге), ни для обсуждения плюсов и минусов всех имеющихся на рынке планировщиков заданий. Я просто хочу резюмировать интеграцию Hangfire и .NET Core.

Оглавление

1. Установите пакет Hangfire NuGet.

На момент написания текущая стабильная версия Hangfire - 1.6.22. Hangfire v1.7.0 скоро выйдет.

После того, как мы создали веб-проект .NET Core (или другие типы проектов, которые позволяют нам внедрять зависимости и / или выполнять аутентификацию), мы можем установить пакет Hangfire NuGet через Visual Studio NuGet Package Manager или установить пакет с помощью инструментов командной строки. .

dotnet add package Hangfire

Пакет Hangfire NuGet включает Hangfire.Core и Hangire.SqlServer. Если вы используете другой поставщик базы данных, вам необходимо установить соответствующий пакет NuGet. Здесь в качестве примера я использую SqlServer.

После установки пакета NuGet у нас будет копия сценария миграции SQL, расположенная в папке C:\Users\{windows user name}\.nuget\packages\hangfire.sqlserver\1.6.22\tools. Скрипт SQL хорошо написан и спроектирован, поэтому при обновлении нашей версии Hangfire мы можем уверенно запустить новый скрипт, включенный в пакет, для обновления схемы базы данных SQL.

Пожалуйста, запустите сценарий SQL, прежде чем продолжить. Если вы используете более новую версию Hangfire, запустите сценарий SQL в своей версии.

2. Определите и выполните фоновое задание.

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

Интерфейс предоставляет один общедоступный метод Task RunAtTimeOf(DateTime now), который можно использовать в модульных тестах или повторно использовать, когда интерфейс внедряется в другие места. Метод Task Run(IJobCancellationToken token) будет использоваться в планировщике заданий Hangfire (мы вернемся к этому моменту в следующем разделе).

3. Составьте планировщик заданий для повторяющихся заданий.

После того, как мы реализовали некоторые фоновые задания, мы хотим запланировать повторяющиеся задания в централизованном классе. Приведенный ниже фрагмент кода показывает скелет типичного планировщика заданий. Для каждого повторяющегося задания мы добавляем (или обновляем) его в коллекцию ReccuringJob в Hangfire, которая создает запись в постоянном хранилище. Повторяющаяся регистрация заданий также позволяет нам указать, когда и как часто задание должно выполняться. Мы можем использовать CRON-выражения для более сложного планирования.

Фактически вызывается метод Run(JobCancellationToken.Null) в классе задания, который мы определили в предыдущем разделе.

Вы можете задаться вопросом, как Hangfire разрешает зависимости для этих повторяющихся заданий. К счастью, Hangfire предоставляет метод расширения (см. Ниже), позволяющий легко подключиться к системе внедрения зависимостей в .NET Core.

4. Добавьте Hangfire в коллекцию служб .NET Core.

Сначала мы хотим зарегистрировать фоновые задания в контейнере служб .NET Core. Например, в методе ConfigureServices(IServiceCollection services) в классе Startup мы регистрируем следующие два класса заданий с определенным образом жизни, чтобы мы могли вызывать эти задания в других службах или контроллерах с помощью внедрения зависимостей.

services.AddScoped<IEmailSendingJob, EmailSendingJob>;
services.AddScoped<IMyJob, MyJob>;

С другой стороны, когда задания выполняются в Hangfire, Hangfire также должен знать их зависимости. Hangfire внутренне использует AspNetCoreJobActivator для поиска необходимых сервисов и создания областей для зарегистрированных заданий. Для интеграции Hangfire с внедрением зависимостей .NET Core Hangfire предоставляет метод расширения services.AddHangfire(), который выполнил всю тяжелую работу, включая регистрацию фабрики регистраторов, регистрацию AspNetCoreJobActivator и так далее. Этот метод расширения также принимает конфигурации Hangfire. См. Код ниже.

Конфигурации можно использовать для настройки JobActivator, для настройки LogProvider и для настройки хранилища сервера Hangfire. Например, приведенный выше фрагмент кода сообщает Hangfire строку подключения для SQL-сервера, интервал опроса очереди заданий и т. Д. Вы можете изучить другие варианты в соответствии с вашими потребностями.

После настройки внедрения зависимостей мы можем настроить приложение для использования сервера Hangfire при запуске приложения, чтобы все фоновые задания и повторяющиеся задания могли начать раскручиваться. В приведенном ниже фрагменте кода мы добавляем несколько строк кода в метод Configure(IApplicationBuilder app, IHostingEnvironment env) в классе Startup. Мы проинструктируем приложение использовать сервер Hangfire, добавить глобальный фильтр и при необходимости сохранить / обновить повторяющиеся задания в хранилище Hangfire.

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

5. Настройте Hangfire Dashboard.

Панель управления Hangfire - отличный инструмент для просмотра статусов фоновых заданий. Чтобы настроить дашборд, не нужно много работать.

Вы могли заметить, что мы добавили метод расширения app.UseHangfireDashboard() во фрагмент кода в приведенном выше разделе. Этот метод расширения принимает параметр пути к приборной панели и параметр опций приборной панели.

Несмотря на то, что все наши вакансии идемпотентны, мы по-прежнему не хотим, чтобы кто-то случайно инициировал / удалил задание, или мы не хотим, чтобы случайный человек видел статусы вакансий. Таким образом, защита приборной панели всегда необходима. Мы можем защитить приборную панель с помощью HangfireDashboardAuthorizationFilter, который можно реализовать, как показано ниже.

При такой настройке мы можем перейти к панели управления Hangfire по URL-адресу “{host-name}/hangfire”, и только пользователи с определенной ролью имеют доступ к панели управления. Конечно, вы можете настроить процесс авторизации в соответствии со своими требованиями.

Это все на сегодня. Следуя вышеуказанным шагам, мы настроили базовое приложение с запущенным сервером Hangfire, и повторяющиеся задания будут выполняться в желаемое время. Не забывайте, что ваша учетная запись исполнителя приложений должна иметь разрешение на запись [Hangfire] схемы в хранилище SQL.

Спасибо.