剖析 Laravel 计划任务--初探

译文GitHub https://github.com/yuansir/diving-laravel-zh

原文链接 https://divinglaravel.com/task-scheduling/before-the-dive

想象这种情况,作为一个大型SaaS的开发者,您需要找到一种在周末每分钟选择10个随机客户的方式,并提供折扣升级,发送折扣的工作可能非常简单,但我们需要每分钟运行一次,为此我分享一些CRON的简要介绍给还不熟悉人。

CRON

CRON是一个守护进程,它驻留在你的linux服务器中,大部分时间都没有唤醒,但是每一分钟它都会睁开双眼,看看是否运行任何给定的任务,你使用crontab文件与该守护进程通信,在大多数常见的设置文件可以位于/etc/crontab,crontab文件可能看起来像这样:

0 0 1 * * /home/full-backup
0 0 * * * /home/partial-backup
30 5 10 * * /home/check-subscriptions

在crontab文件中,每行表示一个计划任务作业,每个作业定义包含两部分:

  1. *****部分代表该作业运行的计时器。
  2. 第二部分是应运行的命令

CRON时序语法

5个星号按顺序排列如下:

  1. 一小时内的分钟
  2. 一天内的小时
  3. 一个月内的日期
  4. 一年内的月份
  5. 一周的内的天

示例:

  • 0 0 1 * * 在第一个例子中,表示该工作应在每月,每个月的第一个天,上午12点,每小时第一分钟运行。 或者简单地说,它应该在每月的第一天上午12:00运行。
  • 0 * * * * 在第二个例子中,表示该工作应该每小时运行一次。
  • 30 5 10 * * 表示该工作应该在每个月10日上午5:30运行

这里还有一些其他的示例:

  • * * * * 3 表示工作应该在星期三每分钟运行一次。
  • * * * * 1-5 表示该工作应该每周一至周五运行。
  • 0 1,15 * * * 表示该工作应该每天在凌晨1点和3点运行两次。
  • */10 * * * * 表示该工作应该每10分钟运行一次。

所以我们为我们的工作注册一个cron任务?

是的,我们可以在我们的crontab文件中注册:

 * * * * php /home/divingLaravel/artisan send:offer

该命令将通知CRON守护程序每分钟运行 php artisan send:offer artisan命令,是不是很容易? 但是,当我们想要在星期四和星期二或每个特定日子里每分钟运行命令时会感到困惑,记住cron作业的语法不是一件容易的事,而且还需要更新crontab文件,你想添加一个新的工作或更新的时间表可能是相当耗时的时间,所以几个版本发布后Laravel添加了一些有趣的功能,为调度任务提供了一个容易记住的语法:

$schedule->command('send:offer')
          ->everyFiveMinutes()
          ->wednesdays();

你只需要在你的crontab中注册一个cron工作,laravel会处理剩下的事:

* * * * * php /divingLaravel/artisan schedule:run >> /dev/null 2>&1

您可以在App\Console\Kernel类的schedule方法中定义预定的命令:

protected function schedule(Schedule $schedule)
{
    $schedule->command('send:offer')
          ->everyFiveMinutes()
          ->wednesdays();
}

如果您想了解有关不同计时器选项的更多信息,请查看 官方文档

当Console Kernel被实例化时,Laravel向内核的booted事件注册一个侦听器,该事件将Scheduler绑定到容器并调用kernel的schedule()方法:

// in Illuminate\Foundation\Console\Kernel

public function __construct(Application $app, Dispatcher $events)
{
    $this->app->booted(function () {
        $this->defineConsoleSchedule();
    });
}

protected function defineConsoleSchedule()
{
     // Register the Scheduler in the Container
    $this->app->instance(
        Schedule::class, $schedule = new Schedule($this->app[Cache::class])
    );

     // Call the schedule() method that we override in our App\Console\Kernel
    $this->schedule($schedule);
}

一旦console kernel完成Kernel类中定义的引导顺序,这个booted事件就被触发。

在Kernel的handle()方法中,Laravel会检查Foundation\Application是否已启动,如果不是调用应用程序的bootstrapWith()方法,并传递在console Kernel定义的引导程序数组。

简单地说:

当CRON守护程序每分钟都调用php artisan schedule:run命令时,控制台Console Kernel将被启动,您在App\Console\Kernel::schedule()方法中定义的作业将被注册到调度程序。

schedule()方法调用Illuminate\Console\Scheduling\Schedule的实例作为唯一的参数,这是用于记录您提供的作业的计划任务管理器,并决定每次CRON守护进程应该运行什么。

转载请注明: 转载自Ryan是菜鸟 | LNMP技术栈笔记

如果觉得本篇文章对您十分有益,何不 打赏一下

本文链接地址: 剖析Laravel计划任务--初探