【问题标题】:Scheduling jobs with high CPU load in Quartz.NET在 Quartz.NET 中调度具有高 CPU 负载的作业
【发布时间】:2011-10-20 08:33:07
【问题描述】:

我正在使用 Quartz.NET 来安排一个从外部源加载大量数据并保存在数据库中的作业。下载它们后,还必须对其进行一些处理,这将在数据库的不同表中创建额外的记录。

下载器作业是有状态的作业,每分钟运行一次。我面临的问题是,在下载数据后,处理部分的时间可能比我预期的要长得多。

我应该如何处理这个问题?我已经考虑在数据下载完成后创建另一个作业(仅运行一次)。在这种情况下,下载器作业可以每分钟运行一次(这是最初的计划),因为下载部分只需要 5-20 秒,而另一个作业可以在下载器完成后处理这些记录。处理器作业将从数据库中获取标记为未处理的记录并对其进行处理。

这是处理处理的正确方法吗?我来的另一个想法是建立一个 WCF 服务来处理一个下载的元素。这将在每个下载的元素上调用。但是我认为这不会比其他工作方法更好。

【问题讨论】:

  • processing part 是 CPU 绑定操作还是涉及繁重的 IO 操作?
  • 高负载下我的意思是CPU负载,所以过程中没有繁重的IO。
  • 好的,你能不能尝试使用 TPL 并行处理这个过程,看看你是否有任何收获,以便在可接受的时间内完成
  • 所以你的意思是在同时负责下载的 Quartz.NET 作业中使用 TPL?我会试试这个速度有多快,但我想保持在 1 分钟的时间范围内,以免延迟下一次下载。

标签: c# wcf c#-4.0 scheduling quartz.net


【解决方案1】:

也许更好的方法应该是将作业用作事件,并让另一个服务执行下载。

该作业只会将定义意图的消息发送到另一个端点。

这在具有某种消息代理或服务总线(如 NServiceBus 或 MassTransit)的事件驱动架构中非常常见。

这样您的调度程序将保持精简和可扩展。

这是一个例子:

public class DownloadFileJob : IJob
{
    public IBus Bus { get; set; }
    public ILogger Logger{ get; set; }

    public void Execute(IJobExecutionContext context)
    {
        Bus.Send(new DownloadFileMessage());
        Logger.Info("Sending message requesting download of file.");
    }
}

【讨论】:

    【解决方案2】:

    您让下载作业安排另一个作业来进行处理的方法是可行的并且被普遍使用。

    但要记住的一件事是,只要下载作业并不总是安排处理作业,它就可以工作。如果您的下载作业总是安排一个作业(例如每分钟),并且预定作业的运行时间比运行时间长,那么您最终会用完处理线程,并且您的下载作业将不得不等待线程可用。

    【讨论】:

    • 嗯,我还没有想过你提到的可能的问题。是否有任何“推荐”的策略或方法来防止这种情况?
    • 您可以在不同的调度程序上运行长时间运行的作业,可能有足够的容量,这样您就不会用完线程。
    • 谢谢。如果我将下载器作业的优先级设置为高,处理时设置为低,那不会解决吗?如果您建议在不同的调度程序上运行它们,我想不会,但值得一问。
    • 优先级仅用于在需要同时触发 2 个触发器时打破平局,因此这不能解决问题。 Quartz.net 根据触发器的下一次触发时间按顺序运行作业。
    【解决方案3】:

    您可能会考虑为下载作业设置JobListener。只需创建一个实现IJobListener 接口的类,然后将处理代码放入JobWasExecuted 方法中:

    public PostDownloadJobListener : IJobListener
    {
        string Name { get { return "MyJobListener"; } }
        void JobToBeExecuted(JobExecutionContext context) { }
        void JobExecutionVetoed(JobExecutionContext context) { }
        void JobWasExecuted(JobExecutionContext context, JobExecutionException jobException)
        {
            // Perform processing here
        }
    }
    

    使用scheduler.AddJobListener(myJobListener);注册监听器,作业执行成功后让监听器处理。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-10-09
      • 2023-04-05
      • 2023-04-04
      • 2013-02-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多