我正试图在larave中安排一些任务,但我发现很难每隔20秒安排一次任务。检查laravel doc。对于laravel schedular,它没有这样的方法秒。虽然有 - > cron(' * * * * * *')"在自定义Cron计划"上运行任务,但它也无法解决我的问题。
以下是我在kernal.php文件中用于安排的代码。
protected function schedule(Schedule $schedule)
{
// need to replace everyMinute() by some other method which can run it every 20 sec
$schedule->call('path\to\controller@method)->everyMinute();
// also tried cron() but didn't workout.
$schedule->call('path\to\controller@method)->cron(*/20 * * * * *);
}
感谢。
答案 0 :(得分:8)
没有任何方法可以为您提供开箱即用的功能,但是有些人提出了与您已经处于同样情况的建议。
->cron(*/20 * * * * *)
实际上是说每20分钟运行一次,而不是每20秒运行一次。鉴于cron没有达到亚分钟分辨率,这可能是Laravel也不支持它的原因。
如果这确实需要每30秒运行一次,那么我会在这里找到两者的组合:Laravel 5 schedule job every 30 seconds和Laravel schedular: execute a command every second
也就是说,您仍然应该每分钟调用一次命令,但添加withoutOverlapping()
方法只是为了安全。
然后在你的命令中你可以运行你的代码,睡20秒,再次运行,睡20秒,然后再运行它。这显然是在您的代码几乎可以即时运行的前提下工作的。 例如,如果您的代码需要5秒钟才能运行,然后您睡眠20秒然后再次运行 - 您的代码实际上每25秒运行一次。
我想你对这段代码的运行时间有了很好的了解。如果没有,请在运行artisan命令时手动计时以获得一个想法 - 这样的事情可能有助于date && php artisan your:command && date
。
这将在shell中输出日期,运行命令然后再次输出日期 - 这包括您可以用来查看运行所需的秒数的时间。
这将要求您将控制器操作重构为命令,或将sleep()
代码添加到控制器操作中。工匠命令的docs应该有帮助。
我建议将其重构为命令,但这取决于你。
//Console command
public function handle()
{
\App\Investment::calculate(); //takes 2 seconds to run
sleep(18); //sleep for 18 seconds to ensure we are only running the command every 20 seconds
\App\Investment::calculate(); //takes 2 seconds to run
sleep(18);
\App\Investment::calculate(); //takes 2 seconds to run
}
//The console scheduler - Kernel.php
protected function schedule(Schedule $schedule)
{
$schedule->call('path\to\controller@method)->everyMinute()->withoutOverlapping();
}
答案 1 :(得分:2)
问题是我们无法在几秒钟内处理调度程序,但我们可以根据执行所花费的时间调用我们的方法次数来定制schedule()方法的更接近的时间,例如:
$obj = new ClassName();
$schedule->call(function () use ($obj) {
sleep(3);
//call method calculate time it takes and based on that we can call method number of methods we want
$obj->method(); //call method
sleep(3); // pause of 3 seconds
$obj->method(); //call again
sleep(3);
$obj->method(); //call again
sleep(3);
})->everyMinute();
在这里,我可以根据执行时间,在一分钟内调用我的方法三次。 谢谢我完成了我的工作。
答案 2 :(得分:1)
出于各种原因,我建议您使用另一种方法,而不是延迟PHP任务处理程序代码。一方面,您在处理程序函数中混用了不同种类的逻辑(定时应由调度程序处理,而不是在任务的代码内)。同样,如果两次延迟之间的通话花费大量时间,您的整体时间也会失真(其本身可以通过测量通话时间并考虑下一次延迟来解决)。但是在第一个呼叫中也可能会有一些异常,导致甚至无法到达后续呼叫。等等
使用cron的一种更常见的方法是简单地添加多个cron作业,并对每个作业施加更大的延迟。所以:
* * * * * cd /path-to-your-project && php artisan schedule:run >> /dev/null 2>&1
* * * * * sleep 20 && cd /path-to-your-project && php artisan schedule:run >> /dev/null 2>&1
* * * * * sleep 40 && cd /path-to-your-project && php artisan schedule:run >> /dev/null 2>&1
这样,您可以确保计划每20秒准确运行一次。 另外,您无需更改PHP代码即可轻松调整频率。
edit:补充并完整;结合以上内容,您必须使用以下时间安排任务:
->cron('* * * * *')
之所以起作用,是因为使用这样的计划,任务总是在计划程序运行时被调用。由于调度程序希望每分钟最多运行一次。回溯验证:
Event::expressionPasses (\illuminate\console\Scheduling\Event.php:296)
CronExpression::isDue (\dragonmantank\cron-expression\src\Cron\CronExpression.php:284)
CronExpression::getNextRunDate (\dragonmantank\cron-expression\src\Cron\CronExpression.php:195)
CronExpression::getRunDate (\dragonmantank\cron-expression\src\Cron\CronExpression.php:322)
答案 3 :(得分:0)
最近,Spatie发布了一个软件包,使您可以在不到一分钟的时间间隔内安排命令。您可以做一些很酷的事情,例如:
protected function shortSchedule(\Spatie\ShortSchedule\ShortSchedule $shortSchedule)
{
// this command will run every second
$shortSchedule->command('artisan-command')->everySecond();
// this command will run every 30 seconds
$shortSchedule->command('another-artisan-command')->everySeconds(30);
// this command will run every half a second
$shortSchedule->command('another-artisan-command')->everySeconds(0.5);
}
答案 4 :(得分:0)
在Laravel 5.7中,-)绝对可以正常工作。
添加app/Console/Kernel.php
$seconds = 5;
$schedule->call(function () use ($seconds) {
$dt = Carbon::now();
$x = 60 / $seconds;
do {
// do your function here that takes between 3 and 4 seconds
\Log::debug($x . ' executing at ' . date('Y-m-d H:i:s'));
time_sleep_until($dt->addSeconds($seconds)->timestamp);
} while ($x-- > 1);
})->everyMinute();