我一直在寻找使用HangFire作为. NET 6的Windows服务,官方文档好像有10年的历史了。其他示例没有指定如何设置工作者服务。无论如何,这是我的环境--我有一个带有api app的Web应用程序。api app是后台作业将排队到HangFire的地方,但我希望实际的处理是在一个不同的服务器上,如应用程序服务器。所以我的目标是创建一个Windows服务,以简单地运行HangFire服务器,并继续让api应用程序来管理作业创建。
我创建了一个新的WorkerService项目,下面是我的代码:
public class Program
{
public static void Main(string[] args) => CreateHostBuilder(args).Build().Run();
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureLogging(logging =>
{
logging.ClearProviders();
logging.AddConsole();
logging.AddEventLog();
})
// Essential to run this as a window service
.UseWindowsService()
.ConfigureServices(configureServices);
private static void configureServices(HostBuilderContext context, IServiceCollection services)
{
var defaultConnection = context.Configuration.GetConnectionString("DefaultConnection");
var hangFireConnection = context.Configuration.GetConnectionString("HangFireConnection");
AppSettings appSettings = context.Configuration.GetSection("AppSettings").Get<AppSettings>();
services.AddLogging();
services.AddHangfire(configuration => configuration
.SetDataCompatibilityLevel(CompatibilityLevel.Version_170)
.UseSimpleAssemblyNameTypeSerializer()
.UseRecommendedSerializerSettings()
.UseSqlServerStorage(hangFireConnection, new SqlServerStorageOptions
{
CommandBatchMaxTimeout = TimeSpan.FromMinutes(5),
SlidingInvisibilityTimeout = TimeSpan.FromMinutes(5),
QueuePollInterval = TimeSpan.Zero,
UseRecommendedIsolationLevel = true,
DisableGlobalLocks = true
}));
services.AddHangfireServer();
services.AddDbContext<PpContext>(options => options.UseSqlServer(defaultConnection), ServiceLifetime.Transient);
services.AddScoped<ExceptionNotifier>();
services.AddHostedService<HangFireWorker>();
JobStorage.Current = new SqlServerStorage(hangFireConnection);
RecurringJob.AddOrUpdate<ExceptionNotifier>("exception-notification", x => x.NotifyByHour(), "0 * * * *"); //runs every hour on the hour
}
}
正如您所看到的,我确实有一个每小时发生一次的循环作业。
对于HangFireWorker类,这是我所拥有的:
public class HangFireWorker : BackgroundService
{
private readonly ILogger<HangFireWorker> _logger;
public HangFireWorker(ILogger<HangFireWorker> logger)
{
_logger = logger;
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
//while (!stoppingToken.IsCancellationRequested)
//{
// _logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now);
// await Task.Delay(1000, stoppingToken);
//}
//there is nothing to do here, hangfire already takes cares of all?
await Task.Delay(0);
}
}
所以我的问题是,我需要在主工作者类中做什么吗?在ExecuteAsync()函数中?我的意思是项目现在工作得很好。我看到服务器在 Jmeter 板(api应用程序)中注册成功。奇怪的是,我只有一个空的工作者类。
任何建议都很感激。
1条答案
按热度按时间2guxujil1#
不需要空的worker类,只需调用
AddHangfireServer
就可以创建一个worker。如果打开
AddHangfireServer
的源代码,您实际上可以看到服务器已注册:AddHangfireServer
将简单地注册一个BackgroundJobServerHostedService
,它将处理所有事情。解决这类问题的一个好策略是在某个时候深入实际的源代码。
这在Hangfire.AspNetCore包的github上也有记录:
在Web应用程序中处理后台任务...
您可以在任何OWIN-compatible应用程序框架中处理后台任务,包括ASP.NET MVC、ASP.NET Web API、FubuMvc、Nancy等。忘记AppDomain卸载、Web Garden和Web Farm问题- Hangfire对于Web应用程序从头开始是可靠的,即使是在共享主机上。
app.UseHangfireServer();
...或其他任何位置在控制台应用程序、Windows服务、Azure工作者角色等中
https://github.com/HangfireIO/Hangfire