我在使用相同数据库的两台服务器上运行了几个 Hangfire 实例。每个实例根据基于服务器名称的某些标准提交要运行的作业,以便没有两个实例运行相同的作业。我注意到它们正在运行相同的作业,这意味着当一个实例运行时,它会选择数据库队列中的任何作业,无论它是否提交了作业。我想在最新的 1.6.x 版本中,每个工作都是独一无二的。似乎这并不意味着它只在创建它的实例上运行?
如何让每个实例只运行它提交的作业?
您需要使用队列来选择处理特定作业的服务器。
这个想法是通过指定一个队列来对作业进行分类。然后对于每个服务器,您将指定它们观看的队列。
在我看来,唯一的问题是为作业选择队列并不简单(除非您使用的是 RecurringJobs)。
当您为服务器启动 Hangfire 实例时,请Queues BackgroundJobServerOptions按照文档使用:
app.UseHangfireServer(new BackgroundJobServerOptions()
{
// order defines priority
// beware that queue names should be lowercase only
Queues = new [] { "critical", "default", "myqueueformyserver" }
});
Run Code Online (Sandbox Code Playgroud)
有两种情况:
经常性工作: RecurringJob.AddOrUpdate("MyFirstRecurringJob", () => myClass.myMethod(), Cron.Minutely(), null, "myqueueformyserver");
BackgroundJobs:您无法在入队时间 ( Hangfire.BackgroundJob.Enqueue(() => myClass.myMethod());)指定作业的队列,因此没有选项。解决方案是使用方法或类属性。Hangfire 提供了一个QueueAttribute:
[Queue("myqueueformyserver")]
public void myMethod() { }
如果我了解您的要求,静态QueueAttribute将不适合您,因为您想动态分配队列。我遇到了同样的情况,并在QueueAttribute的代码的启发下创建了自己的属性。
它看起来像那样(适应您的意愿/需求)
public class MyQueueAttribute : JobFilterAttribute, IElectStateFilter
{
public MyQueueAttribute(string paramQueue)
{
ParamQueue = paramQueue;
}
public string ParamQueue { get; }
public void OnStateElection(ElectStateContext context)
{
var enqueuedState = context.CandidateState as EnqueuedState;
if (enqueuedState != null)
{
enqueuedState.Queue = string.Concat(Environment.MachineName.ToLower(),
ParamQueue);
}
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2285 次 |
| 最近记录: |