Sitecore 预定作业的优先级
Priority of Sitecore scheduled jobs
我有两个 Sitecore 代理,它们 运行 作为计划作业。代理 A 是一个长 运行ning 任务,具有 low 优先级。代理 B 是一个短期 运行ning 任务,具有 高 优先级。 B 运行s 的间隔比 A 的间隔短。
问题是 B 永远不会 运行,而 A 已经 运行ning。
我已经实施 this 以便能够 运行 在内容编辑器中手动代理。当我这样做时,我可以 运行 B 尽管 A 已经 运行ning(即使我在自定义对话框中将它们设置为相同的线程优先级)。
如何在配置文件中指定 B 的优先级高于 A?或者使我的预定作业设置为多线程,以便在 Sitecore 中同时进行 运行 宁个作业?有没有标准的方法来做到这一点?
我尝试了一些 like this 在代理实现中设置线程优先级的方法,但是当 A 已经 运行ning 时,此代码永远不会在 B 中调用。因此,应该以某种方式确定优先级 "before" 工作实施本身。
原因是因为 Sitecore Scheduled Job 按顺序 运行s。因此,如果您有一个正在执行的作业,它在完成之前不会触发其他作业。
如果我没记错的话,sitecore 会将需要在当前 运行ning 作业之后执行的其他作业排队。
由于您使用 运行 代理工具触发作业,因此它将 运行 因为您强制执行。它不会检查是否有另一个作业 运行 除了发布,它会排队,因为它是 t运行 将项目从源数据库转移到目标数据库。
编辑:
您可以从 Web.config 中查看 <job>
的 Sitecore v7.x 或 Sitecore.config 用于 Sitecore v8.x。您将看到用于作业的管道。如果我没记错的话,我认为您需要检查调度程序的代码。命名空间是 Sitecore.Tasks.Scheduler, Sitecore.Kernel
谢谢
正如您可能已经从 Hishaam 的回答中了解到的那样(不再重复这些有用的信息),使用 Sitecore 代理可能不是您尝试做的事情的最佳解决方案。对于类似的设置(需要在电子商务网站上执行导入、导出或其他排队任务的任务),我使用了一个外部调度引擎(在我的例子中,Hangfire 做得很好,但你也可以使用另一个)在我的 Sitecore 解决方案中调用服务。这些服务作为到达 Sitecore 的层执行。
您可以决定要使用这些服务走多远(甚至可以启动新线程),但它们将能够 运行 彼此相邻。这样您就不会遇到另一个进程仍在 运行ning 的问题。我选择了一种架构,其中服务是面向真正业务逻辑的非常薄的一层。
您可能需要确保已经 运行ning 时无法调用一项服务背后的代码(我需要在处理队列的情况下这样做),但这些事情都是可能的.net 代码。
我发现此设置更可靠,尤其是对于重要的任务。当任务需要 运行.
时配置也更容易
正如另一个答案中已经提到的,Sitecore 计划任务是 运行 顺序执行的,因此每个代理 运行 仅在前一个代理完成后才开始。
但是,数据库中定义的任务可以是 运行 async
,这意味着您可以并行安排多个任务到 运行。
您需要创建命令并定义计划:
定义命令
命令在 Sitecore 客户端中定义。
- 在内容编辑器中导航到 /sitecore/system/Tasks/Commands
- 使用命令模板创建新项目
- 指定类型和方法字段。
定义计划
数据库代理将根据计划中的设置执行命令。
- 在内容编辑器中导航到 /sitecore/system/Tasks/Schedules
- 使用计划模板创建新项目
- 对于 Command 字段 select 您刚刚创建的 Command 项目
- 如果任务适用于特定项目,您可以在“项目”字段中识别这些项目。该字段支持多种格式。
- 对于“计划”字段,您确定任务应该在什么时候 运行。此字段的值采用管道分隔格式。
- 在日程表中,检查标记为
Async
的字段。
您可以阅读有关 Database Scheduler in the Sitecore Community Docs 的更多信息。
请注意,如果您并行安排太多任务运行,这可能会导致性能问题。
运行如果您不能像在配置中定义的任务那样传入参数,那么从数据库中执行计划任务的缺点。如果您不能简单地从代码访问配置设置(它们 需要 传入),那么对于配置中定义的计划任务,您可以从计划任务代码调用 Sitecore 作业。 Sitecore 作业 运行 作为一个线程,每个作业都会启动一个新线程,因此可以 运行 并行,只需确保作业名称是唯一的(同名作业将排队)。
我意识到以下解决方案对于 运行 我的高优先级计划任务 B(作为 Sitecore 中的后台代理)不是一个好的解决方案,因此我最终采用了以下解决方案。为了这个答案的目的,我现在打电话给 B:ExampleJob
我创建了一个名为 ExampleJobStarter
的新代理 class。这项工作的目的只是启动另一个线程 运行 实际工作,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
在另一个线程中 运行ning。 ExampleJob
本身将每 10 秒完成一次工作,不受低优先级作业代理的干扰,仍然 运行 作为普通后台代理。
如果你走这条路,请注意死锁问题(在这种情况下,我正在处理的数据不是问题)。
我有两个 Sitecore 代理,它们 运行 作为计划作业。代理 A 是一个长 运行ning 任务,具有 low 优先级。代理 B 是一个短期 运行ning 任务,具有 高 优先级。 B 运行s 的间隔比 A 的间隔短。
问题是 B 永远不会 运行,而 A 已经 运行ning。
我已经实施 this 以便能够 运行 在内容编辑器中手动代理。当我这样做时,我可以 运行 B 尽管 A 已经 运行ning(即使我在自定义对话框中将它们设置为相同的线程优先级)。
如何在配置文件中指定 B 的优先级高于 A?或者使我的预定作业设置为多线程,以便在 Sitecore 中同时进行 运行 宁个作业?有没有标准的方法来做到这一点?
我尝试了一些 like this 在代理实现中设置线程优先级的方法,但是当 A 已经 运行ning 时,此代码永远不会在 B 中调用。因此,应该以某种方式确定优先级 "before" 工作实施本身。
原因是因为 Sitecore Scheduled Job 按顺序 运行s。因此,如果您有一个正在执行的作业,它在完成之前不会触发其他作业。
如果我没记错的话,sitecore 会将需要在当前 运行ning 作业之后执行的其他作业排队。
由于您使用 运行 代理工具触发作业,因此它将 运行 因为您强制执行。它不会检查是否有另一个作业 运行 除了发布,它会排队,因为它是 t运行 将项目从源数据库转移到目标数据库。
编辑:
您可以从 Web.config 中查看 <job>
的 Sitecore v7.x 或 Sitecore.config 用于 Sitecore v8.x。您将看到用于作业的管道。如果我没记错的话,我认为您需要检查调度程序的代码。命名空间是 Sitecore.Tasks.Scheduler, Sitecore.Kernel
谢谢
正如您可能已经从 Hishaam 的回答中了解到的那样(不再重复这些有用的信息),使用 Sitecore 代理可能不是您尝试做的事情的最佳解决方案。对于类似的设置(需要在电子商务网站上执行导入、导出或其他排队任务的任务),我使用了一个外部调度引擎(在我的例子中,Hangfire 做得很好,但你也可以使用另一个)在我的 Sitecore 解决方案中调用服务。这些服务作为到达 Sitecore 的层执行。
您可以决定要使用这些服务走多远(甚至可以启动新线程),但它们将能够 运行 彼此相邻。这样您就不会遇到另一个进程仍在 运行ning 的问题。我选择了一种架构,其中服务是面向真正业务逻辑的非常薄的一层。
您可能需要确保已经 运行ning 时无法调用一项服务背后的代码(我需要在处理队列的情况下这样做),但这些事情都是可能的.net 代码。
我发现此设置更可靠,尤其是对于重要的任务。当任务需要 运行.
时配置也更容易正如另一个答案中已经提到的,Sitecore 计划任务是 运行 顺序执行的,因此每个代理 运行 仅在前一个代理完成后才开始。
但是,数据库中定义的任务可以是 运行 async
,这意味着您可以并行安排多个任务到 运行。
您需要创建命令并定义计划:
定义命令
命令在 Sitecore 客户端中定义。
- 在内容编辑器中导航到 /sitecore/system/Tasks/Commands
- 使用命令模板创建新项目
- 指定类型和方法字段。
定义计划
数据库代理将根据计划中的设置执行命令。
- 在内容编辑器中导航到 /sitecore/system/Tasks/Schedules
- 使用计划模板创建新项目
- 对于 Command 字段 select 您刚刚创建的 Command 项目
- 如果任务适用于特定项目,您可以在“项目”字段中识别这些项目。该字段支持多种格式。
- 对于“计划”字段,您确定任务应该在什么时候 运行。此字段的值采用管道分隔格式。
- 在日程表中,检查标记为
Async
的字段。
您可以阅读有关 Database Scheduler in the Sitecore Community Docs 的更多信息。
请注意,如果您并行安排太多任务运行,这可能会导致性能问题。
运行如果您不能像在配置中定义的任务那样传入参数,那么从数据库中执行计划任务的缺点。如果您不能简单地从代码访问配置设置(它们 需要 传入),那么对于配置中定义的计划任务,您可以从计划任务代码调用 Sitecore 作业。 Sitecore 作业 运行 作为一个线程,每个作业都会启动一个新线程,因此可以 运行 并行,只需确保作业名称是唯一的(同名作业将排队)。
我意识到以下解决方案对于 运行 我的高优先级计划任务 B(作为 Sitecore 中的后台代理)不是一个好的解决方案,因此我最终采用了以下解决方案。为了这个答案的目的,我现在打电话给 B:ExampleJob
我创建了一个名为 ExampleJobStarter
的新代理 class。这项工作的目的只是启动另一个线程 运行 实际工作,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
在另一个线程中 运行ning。 ExampleJob
本身将每 10 秒完成一次工作,不受低优先级作业代理的干扰,仍然 运行 作为普通后台代理。
如果你走这条路,请注意死锁问题(在这种情况下,我正在处理的数据不是问题)。