前言
四月中旬Hangfire团队发布了1.7.11版本,在使用周期性作业调度过程中发现一个问题,这个问题应该一直未解决,故做此记录,希望遇到的童鞋根据项目业务而避开这个问题。
周期性作业调度
我们依然是在控制台中进行测试,下载所需包请参考官方文档,这里不再叙述,首先我们在内存中存储数据,如下:
var storageOpts = new MemoryStorageOptions(); GlobalConfiguration.Configuration.UseMemoryStorage(storageOpts); using var server = new BackgroundJobServer(); RecurringJob.AddOrUpdate("job1", () => Print1(), "*/10 * * * * *", TimeZoneInfo.Local); RecurringJob.AddOrUpdate("job2", () => Print2(), "*/10 * * * * *", TimeZoneInfo.Local); RecurringJob.AddOrUpdate("job3", () => Print3(), "*/10 * * * * *", TimeZoneInfo.Local);
public static void Print1() { Console.WriteLine("start1"); } public static void Print2() { Console.WriteLine("start2"); } public static void Print3() { Console.WriteLine("start3"); }
Hangfire已支持秒级(1.7+)周期作业调度,如上代码,我们每隔10秒执行上述3个作业,打印如下:
基于内存存储间隔10秒执行对应作业,根据上述打印结果来看没有问题,接下来我们使用SQLite来存储作业数据看看,首先下载Hangfire.SQLite包,针对控制台需进行如下配置
GlobalConfiguration.Configuration.UseSQLiteStorage("Data Source=./hangfire.db;");
当我们启动控制台时一定会抛出如下异常,其异常旨在表明需要SQLite驱动
我们去下载微软官方针对SQLite的驱动(Microsoft.Data.Sqlite)
接下来我们将发现对于每一个作业都会重复执行多次,如下:
猜测只会在SQLite数据库中才会存在问题吧,为了解决这个问题,做了一点点尝试,但还是无法从根本上完全解决,我们知道Hangfire服务的默认工作数量为当前机器的处理器数量乘以5即(Environment.ProcessorCount * 5),那么我们尝试给1是不是可以规避这个问题
var options = new BackgroundJobServerOptions() { WorkerCount = 1 }; using var server = new BackgroundJobServer(options);
上述设置后,我们可以看到貌似只执行了一次,但是这种情况还是是随机的并不靠谱,比如多执行几次看看,会出现如下可能情况
没招了,找了下官方issue列表,发现此问题(https://github.com/mobydi/Hangfire.Sqlite/issues/2)一直处于打开状态并未得到解决,所以要么看看能否根据项目业务规避这个问题或者下载源码自行调试解决
总结
本文是在使用Hangfire过程中发现SQLite数据库出现的问题,因针对Hangfire的SQLite具体实现并不是官方团队所提供,所以暂不能确定到底是Hangfire.SQLite包提供者的问题,根据issue描述大概率是Hangfire的一个bug,希望在SQLite存储作业等数据存在的问题引起使用者注意。