Linux操作系统中cron作业条目的经典配置文件如下:
前五个参数指示此任务的执行时间,第六个参数-必须运行的命令本身。时间参数是:分钟,小时,天,月和星期几。此外,所有数字都必须以整数或特殊语法形式表示。结果,启动命令的最小可能间隔是每分钟一次。对于许多任务,更频繁地需要执行命令,例如,每10秒执行一次。对于某些业务流程自动化任务,最大允许延迟通常不超过1-1.5秒。当然,经典的cron不适合此-需要改进。以下是在Linux上为经典cron创建附加功能(使用PHP)并使用防止重启进程的附加保护的分步实现。任务设置和cron设置
例如,我们将使用以下任务:- 在前端,用户可以通过单击“运行”按钮来启动某些复杂任务的执行。
- 将新行写入数据库后,后端将通知用户。
- 通过cron,我们将“跟踪”这些新任务并尽快完成它们,以使用户不会在一分钟内得到结果,而会立即*。
*如果仅每分钟使用一次命令启动,则任务将在秒数达到最接近的零(新的分钟的开始)时开始。因此,在经典形式下,用户将需要等待0到59秒的执行时间。因此,cron将以其最大形式进行配置,即 每分钟一次:* * * * * /usr/bin/php -q /run.php > /dev/null 2>&1
单周期
最初,您应该确定我们将在数据库中请求新任务的频率-依赖于此,周期数和逻辑睡眠(函数sleep
)将发生变化,在当前示例中,将使用10秒的步长。因此,循环数为60/10 =6。总计,通用代码如下:for ($cycle = 1; $cycle <= 6; $cycle++) {
$all_tasks = get_all_tasks();
if ($all_tasks) {
foreach($all_tasks as $one_task) {
solve_one_task($one_task);
}
}
sleep(10);
}
澄清:在此示例中,使用了10秒的步长,这可以提供每10秒一次的最小脚本执行间隔。因此,为了更频繁地执行,您应该更改周期数和“睡眠时间”。避免重复执行任务
在呈现的形式中,存在一种不确定性,即,如果任务已经开始,则重复执行该任务。如果任务“困难”并且需要几秒钟的时间来执行,则尤其如此。这会导致重新执行问题:- 该功能
solve_one_task()
已在运行,但尚未完成其工作; - 因此,在数据库中,任务仍被标记为未完成;
- 下一个周期将再次获得该任务,并
solve_one_task()
使用相同的任务再次运行该功能。
当然,这可以解决,例如,通过为此任务更改数据库中的某些状态。但是我们不会加载数据库:根据我的测试,MYSQL可以接受请求,但不能立即处理它。相差0.5秒可能会导致重复执行-这绝对不适合。同样在这种情况下,我们仅讨论任务的状态,因此最好使用服务器的文件系统。基本验证模型是使用flock
-设置和解锁文件的功能构建的。在PHP执行中,该函数可以表示如下:$lock_file_abs = 'file';
$fp = fopen($lock_file_abs,"w+");
if (flock($fp, LOCK_EX | LOCK_NB)) {
solve_one_task($one_task);
flock($fp, LOCK_UN);
}
else {
}
fclose($fp);
unlink($lock_file_abs);
结果
整个周期的总体视图如下:for ($cycle = 1; $cycle <= 6; $cycle++) {
$all_tasks = get_all_tasks();
if ($all_tasks) {
foreach($all_tasks as $one_task) {
$lock_file_abs = __DIR__.'/locks/run_'.$one_task['id'];
$fp = fopen($lock_file_abs,"w+");
if (flock($fp, LOCK_EX | LOCK_NB)) {
solve_one_task($one_task);
flock($fp, LOCK_UN);
}
else {
}
fclose($fp);
unlink($lock_file_abs);
}
}
sleep(10);
}
因此,这种算法使您可以开始任务处理的循环执行,而不必担心任务将被处理多次。现在,仅需每分钟通过cron运行此代码就足够了,从而又将在其内部运行较小的周期。