我遇到了一个问题,hangfire 上的某些作业使用相同的参数多次排队,这些作业几乎同时排队。
我试图将工人的数量限制为一个,然后用DisableConcurrentExecution
装饰我的方法。
我正在使用sqlserver作为存储。有人遇到过这个问题,有一些技巧可以避免它吗?
PS:我使用了DisableConcurrentExecution
因为在hangfire文档中说互斥体和信号量不能保证只调用一次作业。
PS2:检查我的 hangfire 服务器 我注意到我有两个实例,每个实例都有 1 个工作线程,所以我认为这是一个并行性问题而不是并发问题。
根据 Hangfire 文档,当周期性作业/任务没有标识符时,就会出现重复作业问题:">为每个周期性作业使用唯一标识符,否则您将以单个作业结束。
RecurringJob.AddOrUpdate("some-id", () => Console.WriteLine(), Cron.Hourly);
来源:
- https://gist.github.com/odinserj/a8332a3f486773baa009;
- https://discuss.hangfire.io/t/how-do-i-prevent-creation-of-duplicate-jobs/1222/4;
这项工作对我有用。我用MaximumConcurrentExecutions(1)
装饰了hangfire运行的接口方法。
这并不能单独解决我的问题,因为有多个服务器(自动扩展(。
因此,在启动类中,我创建了另一个 backgroundjobserveroptions 来为此作业创建一个独占服务器,以确保当应用程序纵向扩展时,这不会创建另一个具有另一个队列的服务器,我必须在 sqlserver hangfire.server 中查询并检查我的队列是否已存在。
if(!HangfireServerInfo.QueueExists("queuename", AppSettings.GetConnectionString("Hangfire"))){
var hangfireServerOptions = new BackgroundJobServerOptions { WorkerCount = 1, Queues = new[] {"queuename"} };
app.UseHangfireServer(hangfireServerOptions);
}
public static class HangfireServerInfo
{
public static bool QueueExists(string queueName, string connectionString)
{
using (var connection = new SqlConnection(connectionString))
{
var cmd = connection.CreateCommand();
cmd.CommandText =
$@"SELECT COUNT(*)
FROM {YOURHANGFIRESERVER.server}
WHERE JSON_QUERY(data, '$.queues') = '[""{queueName}""]'";
connection.Open();
var result = (int)cmd.ExecuteScalar();
connection.Close();
return result > 0;
}
}
}
可能是解决它的更好方法,但这有效。