如何让 Hangfire 实例只运行自己的作业?

Ton*_*ich 5 hangfire

我在使用相同数据库的两台服务器上运行了几个 Hangfire 实例。每个实例根据基于服务器名称的某些标准提交要运行的作业,以便没有两个实例运行相同的作业。我注意到它们正在运行相同的作业,这意味着当一个实例运行时,它会选择数据库队列中的任何作业,无论它是否提交了作业。我想在最新的 1.6.x 版本中,每个工作都是独一无二的。似乎这并不意味着它只在创建它的实例上运行?

如何让每个实例只运行它提交的作业?

GôT*_*ôTô 8

您需要使用队列来选择处理特定作业的服务器。

这个想法是通过指定一个队列来对作业进行分类。然后对于每个服务器,您将指定它们观看的队列。

在我看来,唯一的问题是为作业选择队列并不简单(除非您使用的是 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)

为作业选择队列

有两种情况:

  1. 经常性工作: RecurringJob.AddOrUpdate("MyFirstRecurringJob", () => myClass.myMethod(), Cron.Minutely(), null, "myqueueformyserver");

  2. 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)