简体   繁体   中英

Graceful shutdown with Hangfire as a Windows service

I have a Hangfire worker set up as a Windows service and I am trying to make sure it shuts down gracefully (ie completes existing work before shutting down). I've looked at existing Stack Overflow questions and the Hangfire documentation and it doesn't seem to have documentation for how to set up Hangfire as a Windows service for .NET 5. Here is my existing code:

Host.CreateDefaultBuilder(args)
    .ConfigureAppConfiguration(builder => builder.AddJsonFile("appsettings.json", optional: false))
    .ConfigureServices((hostContext, services) =>
    {
        // Register services with container

        services.AddHangfire(configuration => configuration
            .SetDataCompatibilityLevel(CompatibilityLevel.Version_170)
            .UseSimpleAssemblyNameTypeSerializer()
            .UseRecommendedSerializerSettings()
            .UseSqlServerStorage(hostContext.Configuration.GetConnectionString("Hangfire"), new SqlServerStorageOptions
            {
                CommandBatchMaxTimeout = TimeSpan.FromMinutes(5),
                SlidingInvisibilityTimeout = TimeSpan.FromMinutes(5),
                QueuePollInterval = TimeSpan.Zero,
                UseRecommendedIsolationLevel = true,
                DisableGlobalLocks = true
            }));

        services.AddHangfireServer(config =>
        {
            config.Queues = new[] { "myqueue" };
        });
    })
.UseNLog()
.UseWindowsService();

Recently I had a similar issue regarding the graceful shutdown in Hangfire. The official way to use graceful shutdown is to use Cancellation Token in your queues and workers.

If that doesn't work you can either reschedule all your jobs at shutdown on extend shutdown time:

 public void Configure([...], IHostApplicationLifetime applicationLifetime)
 {
     .
     .
     .
     appLifetime.ApplicationStopping.Register(OnShutdownAsync);
 }

    private async void OnShutdownAsync()
    {
        Task task1 = Task.Factory.StartNew(() =>
        {
            var monitoring = JobStorage.Current.GetMonitoringApi();
            Console.WriteLine(monitoring.ProcessingCount());
            for (var i = 0; i < monitoring.ProcessingCount(); i++)
            {
                foreach (var processingJob in monitoring.ProcessingJobs(1000 * i, 1000))
                {
                    BackgroundJob.Requeue(processingJob.Key);
                }
            }
    
            Console.WriteLine(monitoring.ProcessingCount());
        });
    Task task2 = Task.Factory.StartNew(() => Thread.Sleep(TimeSpan.FromSeconds(45)));
    
    Task.WaitAny(task1, task2);
    Console.WriteLine("All threads complete");
    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM