【问题标题】:How to make a Hangfire instance run its own jobs only?如何让 Hangfire 实例只运行自己的作业?
【发布时间】:2017-02-02 21:08:56
【问题描述】:

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

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

【问题讨论】:

  • 我的回答有帮助吗?

标签: hangfire


【解决方案1】:

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

这个想法是通过指定队列来对作业进行分类。然后为每台服务器指定他们观看的队列。

在我看来,唯一的问题是为工作选择队列并不简单(除非您正在使用 RecurringJobs)。

服务器配置

当您为服务器启动 Hangfire 实例时,请按照 the documentation 使用 Queues BackgroundJobServerOptions

app.UseHangfireServer(new BackgroundJobServerOptions()
    {
        // order defines priority
        // beware that queue names should be lowercase only
        Queues = new [] { "critical", "default", "myqueueformyserver" } 
    });

为作业选择队列

有两种情况:

  1. RecurringJobs:RecurringJob.AddOrUpdate("MyFirstRecurringJob", () => myClass.myMethod(), Cron.Minutely(), null, "myqueueformyserver");

  2. BackgroundJobs:您无法在入队时指定作业的队列 (Hangfire.BackgroundJob.Enqueue(() => myClass.myMethod());),没有此选项。解决方案是使用方法或类属性。 Hangfire 提供了一个QueueAttribute:
    [Queue("myqueueformyserver")] public void myMethod() { }

如果我了解您的要求,静态 QueueAttribute 将不适合您,因为您希望动态分配队列。我遇到了同样的情况,并在code of the 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);
        }
    }
}

【讨论】:

  • 是的,谢谢。我昨天正在测试它。似乎该属性没有帮助。看起来这是一个错误。有人在 Hangfire 网站上的 cmets 中提到了同样的问题。在方法中使用队列名称似乎效果更好......到目前为止。
  • @GôTô 你确定这种方法有效吗?我有 1 个数据库和多个应用程序,每个应用程序上运行一个 hangfire 服务器,并根据应用程序名称排列队列名称,因此它们是唯一的。在我注册一个重复性作业后,它被第一次注册的应用程序调用,但之后另一个应用程序试图获取该作业,因此发生一般反射错误。我期望的是每个应用程序上的每个hangfire服务器应该只尝试获取队列名称匹配的作业。
  • 你是否将属性添加到方法中?
  • 对于案例 2(BackgroundJobs),您可以这样做:var hangfireClient = new BackgroundJobClient(); hangfireClient.Create(() => myClass.myMethod(), new Hangfire.States.EnqueuedState("myqueueformyserver"));
猜你喜欢
  • 1970-01-01
  • 2015-08-27
  • 2021-07-30
  • 2021-11-25
  • 2013-12-08
  • 1970-01-01
  • 2016-11-11
  • 2018-05-15
  • 2018-08-01
相关资源
最近更新 更多