zoukankan      html  css  js  c++  java
  • Laravel入坑指南(番外)——任务调度

    Laravel提供了非常强劲的命令行工具(如果还不了解,传送到第8往篇),我们如果想要定期执行某个命令行,可以利用crontab进行定时设置。如果有多个定期的任务,很简单,我们设定多条crontab规则在不同时间段内调度不同的命令即可。

    而Laravel框架内部也提供了这样的调度机制。(当然,还是逃不过crontab的支持)

    首先,我们需要在crontab中添加这么一条规则

    * * * * * php /path-to-your-project/artisan schedule:run >> /dev/null 2>&1

    其次,所有的调度任务都在/app/Console/Kernel.php的schedule函数中进行调度设置

    这个函数中可以调度闭包、可调用对象(包含__invoke的对象)、artisian命令、列队任务以及shell命令。以下以例子进行说明:

    //调度闭包,->daily()即调度选项,每天凌晨零点运行任务
    //关于调度选项后面会统一说明
    $schedule->call(function () {
        DB::table('recent_users')->delete();
    })->daily();
    
    
    //调度可调用对象
    //DeleteRecentUsers类中包含了__invoke魔术方法
    $schedule->call(new DeleteRecentUsers)->daily();
    
    
    //调度artisian命令
    $schedule->command('emails:send --force')->daily();
    $schedule->command(EmailsCommand::class, ['--force'])->daily();
    
    
    //调度列队任务
    $schedule->job(new Heartbeat)->everyFiveMinutes();
    $schedule->job(new Heartbeat, 'heartbeats')->everyFiveMinutes();    //将job投递到heartbeats列队中
    
    
    //调度shell命令
    $schedule->exec('node /home/forge/script.js')->daily();

    常用的调度选项:

    方法 描述
    ->cron('* * * * *'); 在自定义Cron调度上运行任务
    ->everyMinute(); 每分钟运行一次任务
    ->everyFiveMinutes(); 每五分钟运行一次任务
    ->everyTenMinutes(); 每十分钟运行一次任务
    ->everyFifteenMinutes(); 每十五分钟运行一次任务
    ->everyThirtyMinutes(); 每三十分钟运行一次任务
    ->hourly(); 每小时运行一次任务
    ->hourlyAt(17); 每小时第十七分钟运行一次任务
    ->daily(); 每天凌晨零点运行任务
    ->dailyAt('13:00'); 每天13:00运行任务
    ->twiceDaily(1, 13); 每天1:00 & 13:00运行任务
    ->weekly(); 每周运行一次任务
    ->monthly(); 每月运行一次任务
    ->monthlyOn(4, '15:00'); 每月4号15:00运行一次任务
    ->quarterly(); 每个季度运行一次
    ->yearly(); 每年运行一次
    ->timezone('America/New_York'); 设置时区

    额外调度约束选项:

    方法 描述
    ->weekdays(); 只在工作日运行任务
    ->weekends(); 只在周末运行任务
    ->sundays(); 每个星期天运行任务
    ->mondays(); 每个星期一运行任务
    ->tuesdays(); 每个星期二运行任务
    ->wednesdays(); 每个星期三运行任务
    ->thursdays(); 每个星期四运行任务
    ->fridays(); 每个星期五运行任务
    ->saturdays(); 每个星期六运行任务
    ->between($start, $end); 基于特定时间段运行任务
    ->when(Closure); 基于特定测试运行任务
    ->environments($env); 只在指定环境运行任务

    举几个例子:

    // 每周星期一13:00运行一次...
    $schedule->call(function () {
        
    })->weekly()->mondays()->at('13:00');
    
    
    // 工作日的上午8点到下午5点每小时运行...
    $schedule->command('foo')
             ->weekdays()
             ->hourly()
             ->timezone('America/Chicago')
             ->between('8:00', '17:00');
    
    
    //每天7点到22点之间,每小时运行
    $schedule->command('reminders:send')
             ->hourly()
             ->between('7:00', '22:00');
    
    
    //每天23点到4点之外的时间内,每小时运行
    $schedule->command('reminders:send')
             ->hourly()
             ->unlessBetween('23:00', '4:00');
    
    
    //when的闭包返回true时运行
    $schedule->command('emails:send')->daily()->when(function () {
        return true;
    });
    
    
    //skip的闭包返回false时运行
    $schedule->command('emails:send')->daily()->skip(function () {
        return true;
    });

    第三,任务调度的重叠处理

    当下一次任务开始执行时,万一上一次的任务还没有执行完成,新的任务是会执行的。也就是说,有可能出现多次任务重叠执行的情况。

    为了避免这种情况,我们可以使用外部的手段来加锁,比如文件锁flock,或者redis的setnx都可以。但是Laravel非常贴心,已经帮我们准备了这样的机制:

    $schedule->command('emails:send')->withoutOverlapping();    //锁默认24小时失效
    
    $schedule->command('emails:send')->withoutOverlapping(10);    //锁10分钟失效

    第四,任务调度的顺序

    默认情况下,同时调度的多个命令会顺序执行。如果你有一些长时间运行的命令,将会导致随后的命令在预期之后很久才能执行。如果你想要让命令在后台执行以便它们可以同时运,可以使用 runInBackground 方法来实现:

    $schedule->command('analytics:report')
         ->daily()
         ->runInBackground();

    第五,任务输出

    我们可以将任务中的输出重定向覆盖写入或追加写入文件中,便于问题的排查:

    //覆盖写入
    $schedule->command('emails:send')
         ->daily()
         ->sendOutputTo($filePath);
    
    //追加写入
    $schedule->command('emails:send')
         ->daily()
         ->appendOutputTo($filePath);

    最后,任务钩子

    使用 before 和 after 方法,你可以指定在调度任务完成之前和之后要执行的代码:

    $schedule->command('emails:send')
             ->daily()
             ->before(function () {
                 // 任务即将开始...
             })
             ->after(function () {
                 // 任务已经完成...
             });

    好了,Laravel话题到这里正式结束了。关于Laravel还有一些知识点,如果想要深入了解的小伙伴就去看官方文档吧。

    下周开始,博主会进入另一个话题。至于要写什么,嗯,还没想好,大家下周再见:)

    ---------------------------  我是可爱的分割线  ----------------------------

    最后博主借地宣传一下,漳州编程小组招新了,这是一个面向漳州青少年信息学/软件设计的学习小组,有意向的同学点击链接,联系我吧。

  • 相关阅读:
    2.列出目录内容
    mongo2csv
    Python-uiautomator使用说明文档
    uiautomator设备和选择器~Python详解
    hadoop1.2开发环境搭建
    postgresql 查询某一个表中的所有字段
    VolgaCTF 2020 Qualifier Library
    VolgaCTF 2020 Qualifier Newsletter
    2019-2020-2 网络对抗技术 20175211 Exp3 免杀原理与实践
    BJDCTF 2nd Writeup
  • 原文地址:https://www.cnblogs.com/ddcoder/p/13455177.html
Copyright © 2011-2022 走看看