This article brings you relevant knowledge about laravel, which mainly introduces the usage and principles of scheduled tasks. It also explains the related issues of scheduled tasks according to the application scenarios. Below Let's take a look, I hope it will be helpful to everyone.
[Related recommendations: laravel video tutorial]
A website system often has many Scheduled tasks need to be executed. For example, push subscription messages, statistics related data, etc. Linux generally uses crontab to set up and manage scheduled tasks. However, as the number of tasks increases, managing scheduled tasks becomes more troublesome and prone to management confusion. Laravel's solution to this problem is to set up only one scheduled task. All scheduled tasks in the business are processed and judged on this scheduled task, realizing the management of scheduled tasks at the code level.
First configure crontab:
* * * * * php artisan schedule:run >> /dev/null 2>&1
The above means to set the scheduled task to be executed every minute. The specific business configuration is placed in App\Console\Kernel In the schedule method:
class Kernel extends ConsoleKernel{ Protected function schedule(Schedule $schedule) { //综合数据统计 $schedule->command('complex_data_log') ->everyMinute() //每分钟执行一次(除此之外还有,每五、十、十五、三十...,不同方法设置的默认时间不同) ->withoutOverlapping() //防止重复执行 ->onOneServer() //在单台服务器上跑 ->runInBackground() //任务后台运行 //->appendOutputTo('log_path')//日志输出,默认追加 ->sendOutputTo('log_path'); //日志输出,默认覆盖先前日志 }}
Basic principle:
schedule:run This specification is in the vendor\illuminate\console\Scheduling\ScheduleRunCommand class It is defined inside, and the definition form is the same as the general scheduled task:
/** * The console command name. * * @var string */protected $name = 'schedule:run';
When laravel parses the command, the ScheduleRunCommand class is merged with the commands array in the Kernel class:
/** * Get the commands to add to the application. * * @return array */ protected function getCommands() { return array_merge($this->commands, [ 'Illuminate\Console\Scheduling\ScheduleRunCommand', ]); }
So the php artisan schedule:run command is a built-in command of the framework.
When the command is started, it will find the handle method in the class by default for execution:
/** vendor\illuminate\console\Command.php * Execute the console command. * * @param \Symfony\Component\Console\Input\InputInterface $input * @param \Symfony\Component\Console\Output\OutputInterface $output * @return mixed */protected function execute(InputInterface $input, OutputInterface $output){ return $this->laravel->call([$this, 'handle']);}
php The artisan schedule:run command will scan all instructions registered in Kernel::schedule every minute and determine the Whether the instruction has reached the execution cycle, if so, push it into the queue to be executed:
/** * Schedule the event to run every minute. * 代码每分钟执行一次 * @return $this */ public function everyMinute() { return $this->spliceIntoPosition(1, '*'); } /** * Splice the given value into the given position of the expression. * 拼接定时任务表达式 * @param int $position * @param string $value * @return $this */ protected function spliceIntoPosition($position, $value) { $segments = explode(' ', $this->expression); $segments[$position - 1] = $value; return $this->cron(implode(' ', $segments)); }
ScheduleRunCommand::handle function:
/** * Execute the console command. * * @return void */ public function handle() { foreach ($this->schedule->dueEvents($this->laravel) as $event) { if (! $event->filtersPass($this->laravel)) { continue; } $this->runEvent($event); } }
Avoid task overlap:
Sometimes the execution time of a single scheduled task is too long. After the next execution time, the last execution task has not been completed. At this time, we can use the withoutOverlapping() method to avoid task overlap. In the withoutOverlapping method, lock the corresponding task (the same is true for the onOneServer method):
public function create(Event $event){ return $this->cache->store($this->store)->add( $event->mutexName(), true, $event->expiresAt );}
Only when the corresponding task lock is obtained can the task be executed:
/** * Run the given event. * 运行任务 * @param \Illuminate\Contracts\Container\Container $container * @return void */ public function run(Container $container) { if ($this->withoutOverlapping && ! $this->mutex->create($this)) { return; } //判断是否是后台运行 $this->runInBackground ? $this->runCommandInBackground($container) : $this->runCommandInForeground($container); }
The task runs in the background :
Since scheduled tasks are executed in sequence, the execution time of the previous task is too long, which will affect the execution time of the next task. Therefore, we can use the runInBackground method to execute the task in the background, which is somewhat similar to a shell. The role of &:
/** * Build the command for running the event in the background. * 构建定时任务后台运行语句 * @param \Illuminate\Console\Scheduling\Event $event * @return string */ protected function buildBackgroundCommand(Event $event) { $output = ProcessUtils::escapeArgument($event->output); $redirect = $event->shouldAppendOutput ? ' >> ' : ' > '; $finished = Application::formatCommandString('schedule:finish').' "'.$event->mutexName().'"'; return $this->ensureCorrectUser($event, '('.$event->command.$redirect.$output.' 2>&1 '.(windows_os() ? '&' : ';').' '.$finished.') > ' .ProcessUtils::escapeArgument($event->getDefaultOutput()).' 2>&1 &' ); }
In addition to the above method, we can also use laravel's scheduled tasks to call Shell commands:
$schedule->exec('node /home/forge/script.js')->daily();
You can also use closure Package scheduling:
$schedule->call(function () { DB::table('recent_users')->delete();})->daily();
If you want to know more about how to use it, you can check laravel’s documentation:
https://laravelacademy.org/post/19517.html
[Related recommendations: laravel video tutorial]
The above is the detailed content of Detailed explanation of laravel scheduled task usage and principles. For more information, please follow other related articles on the PHP Chinese website!