Вопрос или проблема
У нас есть Windows-служба, которая делает резервную копию базы данных каждое утро. Сейчас мы пытаемся сделать резервную копию базы данных с помощью скрипта на C#
, используя Hangfire. Наш план прост: просто делать резервную копию каждое утро в указанное время. В качестве демонстрационного примера я реализовал резервное копирование базы данных на серверной стороне, но каким-то образом застрял на запуске процесса в фоне с помощью Hangfire. На данный момент я пытался делать резервное копирование каждую минуту для тестирования без каких-либо http
запросов. Вот что я попробовал:
public static void RegisterApplicationServices(this IServiceCollection services, IConfiguration configuration)
{
services.AddControllers();
// Получение строки подключения из APPSETTINGS.JSON
var ConnectionString = configuration.GetConnectionString("DbConnectionString");
// Сервисы
services.AddScoped<IBackGroundJobService, CustomJobService>();
// Репозитории
services.AddScoped<ICustomJob, CustomJobRepository>();
var sqlStorage = new SqlServerStorage(ConnectionString);
var options = new BackgroundJobServerOptions
{
ServerName = "Тестовый сервер"
};
JobStorage.Current = sqlStorage;
services.AddHangfire(configuration => configuration
.SetDataCompatibilityLevel(CompatibilityLevel.Version_170).UseSimpleAssemblyNameTypeSerializer()
.UseRecommendedSerializerSettings().UseSqlServerStorage(ConnectionString, new SqlServerStorageOptions
{
CommandBatchMaxTimeout = TimeSpan.FromMinutes(5),
SlidingInvisibilityTimeout = TimeSpan.FromMinutes(5),
QueuePollInterval = TimeSpan.Zero,
UseRecommendedIsolationLevel = true,
DisableGlobalLocks = true
}));
RecurringJob.AddOrUpdate<IBackGroundJobService>("Резервное копирование базы данных", service => service.RunJob(), Cron.Minutely);
services.AddHangfireServer();
}
Служба реализована следующим образом, она работает нормально и проверена с помощью http
запроса:
public class CustomJobService : IBackGroundJobService
{
private readonly ICustomJob _customJobRepository;
public CustomJobService(ICustomJob customJobRepository)
{
_customJobRepository = customJobRepository;
}
public async Task RunJob()
{
await Task.Run(() => _customJobRepository.RunJob());
}
}
Приведенный выше код работает, но он не запускает службу каждую минуту для создания резервной копии. Чтобы это исправить, я написал следующее:
RecurringJob.AddOrUpdate<IBackGroundJobService>("Резервное копирование базы данных", service => service.RunJob(), Cron.Minutely);
Есть ли какая-либо другая конфигурация, которую я упустил, или способ, которым я могу реализовать вышеупомянутое с помощью Hangfire без создания каких-либо запросов или триггеров?
Ответ или решение
Чтобы настроить регулярное резервное копирование базы данных с помощью Hangfire в C#, необходимо осуществить несколько шагов. Из вашего описания видно, что вы уже сделали значительные успехи, но есть некоторые особенности, которые могут привести к проблемам с выполнением фоновых задач.
1. Настройка Hangfire
Перед тем как перейти к основным моментам конфигурации, убедитесь, что вы правильно настроили Hangfire в своем приложении. Ваш код для регистрации Hangfire выглядит корректно, но давайте немного разберем каждую деталь.
public static void RegisterApplicationServices(this IServiceCollection services, IConfiguration configuration)
{
services.AddControllers();
var ConnectionString = configuration.GetConnectionString("DbConnectionString");
services.AddScoped<IBackGroundJobService, CustomJobService>();
services.AddScoped<ICustomJob, CustomJobRepository>();
var sqlStorage = new SqlServerStorage(ConnectionString);
JobStorage.Current = sqlStorage;
services.AddHangfire(configuration => configuration
.SetDataCompatibilityLevel(CompatibilityLevel.Version_170)
.UseSimpleAssemblyNameTypeSerializer()
.UseRecommendedSerializerSettings()
.UseSqlServerStorage(ConnectionString, new SqlServerStorageOptions
{
CommandBatchMaxTimeout = TimeSpan.FromMinutes(5),
SlidingInvisibilityTimeout = TimeSpan.FromMinutes(5),
QueuePollInterval = TimeSpan.Zero,
UseRecommendedIsolationLevel = true,
DisableGlobalLocks = true
}));
RecurringJob.AddOrUpdate<IBackGroundJobService>("Database Backup", service => service.RunJob(), Cron.Minutely);
services.AddHangfireServer();
}
2. Проверка подключения Hangfire
Убедитесь, что Hangfire действительно запущен в фоновом режиме. Для этого вам нужно добавить соответствующий middleware в метод Configure
вашего Startup.cs
:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseHangfireDashboard(); // Для отображения дашборда Hangfire
app.UseHangfireServer(); // Это запуск сервера Hangfire
// Другие middleware...
}
3. Повторяющиеся задачи
Ваш код для добавления повторяющейся задачи выглядит корректно. Убедитесь, что метод RunJob
правильно внедряется через интерфейс IBackGroundJobService
. Кроме того, вызов await Task.Run(() => _customJobRepository.RunJob());
в RunJob
должен выполнять реальную логику резервного копирования. Убедитесь, что метод RunJob
в ICustomJob
максимально оптимизирован и не блокирует поток.
4. Проверка состояния задач
Вы можете использовать Hangfire Dashboard, чтобы проверить состояние ваших фоновых задач. Если задачи выполняются успешно, но не каждый минуту, возможно, вам нужно проверить другие настройки. Например, убедитесь, что нет блокировок или исключений, которые могут мешать выполнению.
5. Ожидание фоновых задач
Hangfire выполняет фоновые задачи в отдельных потоках, что значит, что они должны проходить независимо от HTTP-запросов. Это означает, что ваши задачи должны запускаться даже без непосредственного запроса к API. Однако если сервер останавливается или обнаруживает появление ошибок, это может препятствовать выполнению задач.
Заключение
Убедитесь, что все зависимости правильно инъектированы, и проверьте состояние ваших задач через Hangfire Dashboard. Это поможет вам определить, почему задачи не выполняются согласно вашему ожиданию. Также полезно просмотреть журналы ошибок, чтобы решить любую другую проблему, которая может воспрепятствовать успешному выполнению ваших резервных копий. Если будет необходимость, рассмотрите использование дополнительных методов для повышения надежности, таких как автоматическое повторное выполнение неудачных задач.
Следуя этим шагам, вы сможете успешно настроить резервное копирование базы данных с использованием Hangfire каждые минуту и обеспечить надежную работу вашего приложения.