Sitecore预定作业的优先级

时间:2016-06-03 14:56:46

标签: multithreading sitecore scheduled-tasks

我有两个Sitecore代理程序作为计划作业运行。代理A是一个长期运行的任务,具有优先级。代理B是一个短期运行的任务,具有优先级。 B以比A的间隔短的间隔运行。

问题是当A已经在运行时,B永远不会运行。

我已经实现了this,以便能够在内容编辑器中手动运行代理。当我这样做时,我能够运行B,虽然A已经在运行(即使我在自定义对话框中将它们设置为相同的线程优先级)。

如何在配置文件中指定B的优先级高于A?或者使我的预定作业设置为多线程,以便在Sitecore中同时运行作业?有没有标准的方法来做到这一点?

我尝试了like this,我在代理实现中设置了线程优先级,但是当A已经运行时,从不在B中调用此代码。所以优先排序应该以某种方式完成"之前"工作实施本身。

4 个答案:

答案 0 :(得分:4)

正如在另一个答案中已经提到的,Sitecore计划任务是按顺序运行的,因此每个代理仅在前一个代理完成后运行。

但是,数据库中定义的任务可以运行async,这意味着您可以安排多个任务以并行方式运行。

您需要创建一个Command并定义一个Schedule:

定义命令

命令在Sitecore客户端中定义。

  1. 在内容编辑器中,导航到/ sitecore / system / Tasks / Commands
  2. 使用命令模板
  3. 创建新项目
  4. 指定“类型”和“方法”字段。
  5. 定义时间表

    数据库代理将根据计划中的设置执行命令。

    1. 在内容编辑器中,导航到/ sitecore / system / Tasks / Schedules
    2. 使用“计划模板”
    3. 创建新项目
    4. 对于“命令”字段,请选择刚刚创建的“命令”项目
    5. 如果任务适用于特定项目,则可以在“项目”字段中标识这些项目。该字段支持两种格式。
    6. 对于“计划”字段,您可以确定任务应在何时运行。此字段的值采用管道分隔格式。
    7. 在计划表中,选中标记为Async
    8. 的字段

      您可以详细了解Database Scheduler in the Sitecore Community Docs

      请注意,如果您安排太多任务并行运行,这可能会导致性能问题。

      如果您无法为config中定义的任务传递参数,则从数据库运行计划任务的缺点。如果您不能简单地从代码访问配置设置(并且需要传入),那么对于在配置中定义的计划任务,您可以从计划任务代码中调用Sitecore作业。 Sitecore Jobs作为一个线程运行,每个作业都会启动一个新线程,因此可以并行运行,只需确保作业名称是唯一的(同名作业将排队)。

答案 1 :(得分:1)

原因是因为Sitecore计划作业按顺序运行。因此,如果您正在执行某项工作,则在完成之前不会触发其他工作。

如果我没有弄错的话,sitecore会将当前正在运行的作业后需要执行的其他作业排队。

由于您使用运行代理工具触发作业,因此您将强制执行该代理。除了发布之外,它不会检查是否有其他作业正在运行,它将排队,因为它正在将项目从Source转移到Target数据库。

修改

您可以从Sitecore v8.x的 Web.config 或针对Sitecore v8.x的 Sitecore.config 查看<job>。您将看到用于作业的管道。如果我没有弄错,我认为您需要检查调度程序的代码。命名空间为Sitecore.Tasks.Scheduler, Sitecore.Kernel

由于

答案 2 :(得分:1)

正如您可能已经从Hishaam的回答中了解到的那样(不会重复这些好的信息),使用Sitecore代理可能不是您尝试做的最佳解决方案。对于类似的设置(需要在电子商务站点上执行导入,导出或其他排队任务的任务),我使用了外部调度引擎(在我的案例中,Hangfire可以很好地完成工作,但你也可以使用其他工具)在我的Sitecore解决方案中调用服务。作为到达Sitecore的图层执行的服务。

您可以决定使用这些服务的程度(甚至可以启动新线程),但它们可以彼此相邻运行。这样您就不会遇到另一个进程仍在运行的问题。我选择了一个架构,在这个架构中,服务非常薄,面向真正的业务逻辑。

您可能需要确保在运行时无法调用一个服务背后的代码(我需要在处理队列时执行此操作),但这些内容都可以在.net代码中完成。

我发现这种设置更加强大,特别是对于重要的任务。在需要运行任务时,它也更容易配置。

答案 3 :(得分:0)

在意识到运行我的高优先级计划任务B作为Sitecore中的后台代理不是一个好的解决方案后,我最终得到了以下解决方案。为了这个答案,我现在打电话给B:ExampleJob

我创建了一个名为ExampleJobStarter的新代理类。这项工作的目的只是启动另一个运行实际工作的线程ExampleJob

public class ExampleJobStarter
{
    public override void Run()
    {
        if (ExampleJob.RunTheExampleJob) return;
        ExampleJob.RunTheExampleJob = true;
        Task.Run(() => new ExampleJob().Run());
    }
}

public class ExampleJob
{
    public static bool RunTheExampleJob;

    public override void Run()
    {
        while (RunTheExampleJob)
        {
            DoWork();
            Thread.Sleep(10000);
        }
    }

    private void DoWork()
    {
        ... // here I perform the actual work
    }
}

ExampleJobStarter现已在我的Sitecore配置文件中注册,每10分钟运行一次。我还从Sitecore配置中删除了ExampleJob,因此它不会自动运行(因此,它本身不再是Sitecore作业)。 ExampleJobStarter只会确保ExampleJob正在另一个线程中运行。 ExampleJob本身将每10秒完成一次工作,而不会被仍然作为普通后台代理运行的低优先级作业代理干扰。

如果沿着这条路走下去,请注意死锁问题(对于我在这种情况下使用的数据不是问题)。