任务调度 | 进阶系列 | Laravel 6 中文文档


本站和网页 https://xueyuanjun.com/post/19967.html 的作者无关,不对其内容负责。快照谨为网络故障时之索引,不代表被搜索网站的即时页面。

任务调度 | 进阶系列 | Laravel 6 中文文档
Laravel 学院
文档
Laravel 8.x 中文文档
Laravel 7.x 中文文档
Laravel 6.x 中文文档
Laravel 5.8 中文文档
Laravel 5.7 中文文档
Laravel 5.6 中文文档
Laravel 5.5 中文文档
Laravel 5.4 中文文档
Laravel 5.3 中文文档
Laravel 5.2 中文文档
Laravel 5.1 中文文档
Lumen 中文文档
全栈教程
PHP 全栈工程师指南
PHP 入门到实战
Laravel 入门到精通
Vue.js 入门到实战
玩转 PhpStorm 教程
Laravel 博客入门项目
Laravel 微信小程序项目
Laravel 前后端分离项目
Swoole 入门到实战
Eloquent 性能优化实战
Redis 高性能实战系列
Laravel 新版本特性
PHP 新特性与最佳实践
Golang
Go 入门教程
Go Web 编程
Gin 使用教程
微服务开发
内功修炼
数据结构与算法
网络协议
微服务从入门到实践
高性能 MySQL 实战
高性能 Redis 实战
Laravel 消息队列实战
Laravel 从学徒到工匠
PHP 设计模式系列
名企面试指南
资源库
Laravel 资源大全
Laravel 开源项目
Laravel 扩展包
Laravel 资源下载
更多
博客 & 新闻
问答 & 讨论
Leetcode 题解
学院君读书笔记系列
关于 Laravel 学院
Laravel 互助学习群
Golang 互助学习群
更多
Laravel 中文文档
Laravel 全栈教程
Laravel 学习路径
Go 入门教程
程序员内功修炼
博客
问答
搜索
注册
登录
Info
Content
章节导航
Laravel 6 中文文档
目录索引
序言
3篇文章
新版特性
升级指南
贡献指南
快速入门
5篇文章
安装配置
目录结构
重量级开发环境:Homestead
轻量级开发环境:Valet
部署应用到服务器
核心架构
5篇文章
一次 Laravel 请求的生命周期
服务容器
服务提供者
门面
契约
基础组件
12篇文章
路由
中间件
CSRF 保护
控制器
HTTP 请求
HTTP 响应
视图
URL 生成
Session
表单验证
异常处理
日志
前端开发
4篇文章
Blade 模板引擎
本地化
快速入门:JavaScript & CSS 脚手架
使用进阶:通过 Laravel Mix 编译前端资源
安全系列
7篇文章
登录认证
API 认证
授权
邮箱验证
加密
哈希
重置密码
进阶系列
12篇文章
Artisan 控制台
广播
缓存
集合
事件
文件存储
辅助函数
邮件
通知
扩展包开发
队列
任务调度
数据库操作
6篇文章
快速入门
查询构建器
分页
迁移
数据填充
Redis
Eloquent模型
6篇文章
快速入门
关联关系
集合
API 资源类
访问器和修改器
序列化
测试系列
6篇文章
快速入门
HTTP 测试
浏览器测试
控制台测试
数据库测试
模拟
官方扩展包
7篇文章
订阅支付解决方案:Laravel Cashier
远程操作解决方案:Laravel Envoy
队列系统解决方案:Laravel Horizon
API 认证解决方案:Laravel Passport
全文搜索解决方案:Laravel Scout
第三方登录解决方案:Laravel Socialite
本地开发调试解决方案:Laravel Telescope
图书
Laravel 6 中文文档
进阶系列
任务调度
任务调度
由 学院君 创建于3年前, 最后更新于 3年前
版本号 #1
8477 views
1 likes
0 collects
简介
Cron 是 UNIX、SOLARIS、LINUX 下的一个十分有用的工具,通过 Cron 脚本能使计划任务定期地在系统后台自动运行。这种计划任务在 UNIX、SOLARIS、LINUX下术语为 Cron Jobs。Crontab 则是用来记录在特定时间运行的 Cron 的一个脚本文件,Crontab 文件的每一行均遵守特定的格式:
我们可以在服务器上通过 crontab -e 来新增或编辑 Cron 条目,通过 crontab -l 查看已存在的 Cron 条目。更多关于 Cron 的原理和使用细节请自行百度或 Google。
在以前,开发者需要为每一个需要调度的任务编写一个 Cron 条目,这是很让人头疼的事。你的任务调度不在源码控制中,你必须使用 SSH 登录到服务器然后添加这些 Cron 条目。
Laravel 命令调度器允许你流式而又不失优雅地在 Laravel 中定义命令调度,并且服务器上只需要一个 Cron 条目即可。任务调度定义在 app/Console/Kernel.php 文件的 schedule 方法中,该方法中已经包含了一个示例。
开启调度器
下面是你唯一需要添加到服务器的 Cron 条目,如果你不知道如何添加 Cron 条目到服务器,可以考虑使用诸如 Laravel Forge 这样的服务来为管理 Cron 条目:
* * * * * php /path-to-your-project/artisan schedule:run >> /dev/null 2>&1
该 Cron 将会每分钟调用一次 Laravel 命令调度器,当 schedule:run 命令执行后,Laravel 评估你的调度任务并运行到期的任务。
定义调度
你可以在 App\Console\Kernel 类的 schedule 方法中定义所有调度任务。让我们从一个调度任务的例子开始,在这个例子中,我们将会在每天午夜调度一个被调用的闭包。在这个闭包中我们将会执行一个数据库操作来清空表:
<?php
namespace App\Console;
use Illuminate\Support\Facades\DB;
use Illuminate\Console\Scheduling\Schedule;
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
class Kernel extends ConsoleKernel
/**
* 应用提供的Artisan命令
* @var array
*/
protected $commands = [
//
];
/**
* 定义应用的命令调度
* @param \Illuminate\Console\Scheduling\Schedule $schedule
* @return void
* @translator laravelacademy.org
*/
protected function schedule(Schedule $schedule)
$schedule->call(function () {
DB::table('recent_users')->delete();
})->daily();
除了使用闭包进行调度之外,还可以使用可调用对象。可调用对象是包含 __invoke 方法的简单 PHP 类:
$schedule->call(new DeleteRecentUsers)->daily();
调度 Artisan 命令
除了调度闭包调用外,还可以调度 Artisan 命令和操作系统命令。例如,可以使用 command 方法通过命令名或类来调度一个 Artisan 命令:
$schedule->command('emails:send --force')->daily();
$schedule->command(EmailsCommand::class, ['--force'])->daily();
调度队列任务
job 方法可用于调度一个队列任务,通过该方法可以很方便地调度任务而不必调用 call 方法手动创建闭包来推送任务到队列:
$schedule->job(new Heartbeat)->everyFiveMinutes();
// Dispatch the job to the "heartbeats" queue...
$schedule->job(new Heartbeat, 'heartbeats')->everyFiveMinutes();
调度 Shell 命令
exec 方法可用于调用操作系统命令:
$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();
每周运行一次任务
->weeklyOn(1, '8:00');
每周一上午8点运行一次任务
->monthly();
每月运行一次任务
->monthlyOn(4, '15:00');
每月4号15:00运行一次任务
->quarterly();
每个季度运行一次
->yearly();
每年运行一次
->timezone('America/New_York');
设置时区
这些方法可以和额外的约束一起联合起来创建一周特定时间运行的、更加细粒度的调度,例如,要在每周一调度一个命令:
$schedule->call(function () {
// 每周星期一13:00运行一次...
})->weekly()->mondays()->at('13:00');
// 工作日的上午8点到下午5点每小时运行...
$schedule->command('foo')
->weekdays()
->hourly()
->timezone('America/Chicago')
->between('8:00', '17:00');
下面是额外的调度约束列表:
方法
描述
->weekdays();
只在工作日运行任务
->weekends();
只在周末运行任务
->sundays();
每个星期天运行任务
->mondays();
每个星期一运行任务
->tuesdays();
每个星期二运行任务
->wednesdays();
每个星期三运行任务
->thursdays();
每个星期四运行任务
->fridays();
每个星期五运行任务
->saturdays();
每个星期六运行任务
->between($start, $end);
基于特定时间段运行任务
->when(Closure);
基于特定测试运行任务
->environments($env);
只在指定环境运行任务
介于时间的约束条件
between 方法用于限定一天中特定时间段的任务执行:
$schedule->command('reminders:send')
->hourly()
->between('7:00', '22:00');
类似地,unlessBetween 方法用于排除指定时间段任务的执行:
$schedule->command('reminders:send')
->hourly()
->unlessBetween('23:00', '4:00');
真理测试的约束条件
when 方法用于限制任务基于给定真理测试的结果执行。换句话说,如果给定闭包返回true,只要没有其它约束条件阻止任务运行,该任务就会执行:
$schedule->command('emails:send')->daily()->when(function () {
return true;
});
skip 方法和 when 相反,如果 skip 方法返回true,调度任务将不会执行:
$schedule->command('emails:send')->daily()->skip(function () {
return true;
});
使用 when 方法链的时候,调度命令将只会执行返回 true 的 when 方法。
环境约束
environments 方法可用于只在给定环境执行任务:
$schedule->command('emails:send')
->daily()
->environments(['staging', 'production']);
时区
使用 timezone 方法你可以指定调度任务的执行时间在给定时区内切换:
$schedule->command('report:generate')
->timezone('America/New_York')
->at('02:00')
如果你想为所有调度任务分配了同样的时区,可以在 app/Console/Kernel.php 文件中定义一个 scheduleTimezone 方法。该方法返回分配给所有调度任务的默认时区:
/**
* Get the timezone that should be used by default for scheduled events.
* @return \DateTimeZone|string|null
*/
protected function scheduleTimezone()
return 'America/Chicago';
注:请记住有些时区会使用夏令时,当夏令时改变时,你的调度任务有可能会运行两次或者根本不会运行,因此,建议你最好不要使用这种时区调度。
避免任务重叠
默认情况下,即使前一个任务仍然在运行调度任务也会运行,要避免这样的情况,可使用 withoutOverlapping 方法:
$schedule->command('emails:send')->withoutOverlapping();
在本例中,Artisan 命令 emails:send 每分钟都会运行 —— 如果该命令没有在运行的话。如果你的任务在执行时经常大幅度的变化,那么 withoutOverlapping 方法就非常有用,你不必再去预测给定任务到底要消耗多长时间。
如果需要的话,你可以指定"without overlapping"锁失效前的分钟数,默认情况下,这个锁会在 24 小时后失效:
$schedule->command('emails:send')->withoutOverlapping(10);
在单台服务器上运行任务
注:要使用这个功能,必须使用 memcached 或 redis 缓存驱动作为应用默认的缓存驱动。此外,所有服务器必须和同一个中央缓存服务器通信。
如果你的应用运行在多台服务器上,可能需要限制调度任务只在某台服务器上运行。例如,假设你有一个每个星期五晚上生成新报告的调度任务,如果任务调度器运行在三台服务器上,调度任务会在三台服务器上运行并且生成三次报告,不够优雅!
要告知任务只在单台服务器上运行,在定义调度任务时使用 onOneServer 方法即可。第一台获取到该任务的服务器会给任务上一把原子锁以阻止其他服务器同时运行该任务:
$schedule->command('report:generate')
->fridays()
->at('17:00')
->onOneServer();
后台任务
默认情况下,同时调度的多个命令会顺序执行。如果你有一些长时间运行的命令,将会导致随后的命令在预期之后很久才能执行。如果你想要让命令在后台执行以便它们可以同时运,可以使用 runInBackground 方法来实现:
$schedule->command('analytics:report')
->daily()
->runInBackground();
注:runInBackground 方法只有在通过 command 和 exec 方法调度任务时才可以使用。
维护模式
当 Laravel 处于维护模式时,调度任务不会运行,不过,如果你想要在维护模式期间强制运行任务,可以使用 evenInMaintenanceMode 方法:
$schedule->command('emails:send')->evenInMaintenanceMode();
任务输出
Laravel 调度器为处理调度任务输出提供了多个方便的方法。首先,使用sendOutputTo 方法,你可以发送输出到文件以便稍后检查:
$schedule->command('emails:send')
->daily()
->sendOutputTo($filePath);
如果你想要追加输出到给定文件,可以使用 appendOutputTo 方法:
$schedule->command('emails:send')
->daily()
->appendOutputTo($filePath);
使用 emailOutputTo 方法,你可以将输出通过邮件发送给接收人。使用邮件发送任务输出之前,需要配置 Laravel 的邮件服务:
$schedule->command('foo')
->daily()
->sendOutputTo($filePath)
->emailOutputTo('foo@example.com');
注:emailOutputTo、emailOutputOnFailure、sendOutputTo 和 appendOutputTo 方法只对 command 和 exec 方法有效。
任务钩子
使用 before 和 after 方法,你可以指定在调度任务完成之前和之后要执行的代码:
$schedule->command('emails:send')
->daily()
->before(function () {
// 任务即将开始...
})
->after(function () {
// 任务已经完成...
});
onSuccess 和 onFailure 方法允许你在调度任务成功或失败的情况下执行指定的代码:
$schedule->command('emails:send')
->daily()
->onSuccess(function () {
// The task succeeded...
})
->onFailure(function () {
// The task failed...
});
Ping URL
使用 pingBefore 和 thenPing方法,调度器可以在任务完成之前和之后自动 ping 给定的 URL。该方法在通知外部服务时很有用,例如 Laravel Envoyer,在调度任务开始或完成的时候:
$schedule->command('emails:send')
->daily()
->pingBefore($url)
->thenPing($url);
使用 pingBefore($url) 和 thenPing($url) 方法可用于只有在给定条件为 true 时才 ping 给定的 URL:
$schedule->command('emails:send')
->daily()
->pingBeforeIf($condition, $url)
->thenPingIf($condition, $url);
pingOnSuccess 和 pingOnFailure 方法可用于在任务成功或失败的情况下 ping 指定的 URL:
$schedule->command('emails:send')
->daily()
->pingOnSuccess($successUrl)
->pingOnFailure($failureUrl);
所有这些 ping 方法都需要安装 HTTP 库 Guzzle,可以使用 Composer 包管理器来安装 Guzzle 依赖到项目:
composer require guzzlehttp/guzzle
shell
Crontab
后台
服务器
输出
ping
时区
环境
命令
Laravel
队列
Artisan
Cron
任务
任务调度
文档
6.0
点赞
取消点赞
收藏
取消收藏
赞赏
分享到以下平台:
<< 上一篇:
队列
>> 下一篇:
快速入门
1 条评论
#1
frans
评论于 2年前
正在删除评论...
在laravels常驻情况下使用 withoutOverlapping 是否一定要指定过期时间,不然第二天任务会停止执行 ?
登录后即可添加评论
升级为学院君订阅用户(新年优惠🎁)
内容导航
简介
开启调度器
定义调度
调度 Artisan 命令
调度队列任务
调度 Shell 命令
调度常用选项
时区
避免任务重叠
在单台服务器上运行任务
后台任务
维护模式
任务输出
任务钩子
相关推荐
任务调度
Laravel 5.7 中文文档
进阶系列
任务调度
Laravel 5.8 中文文档
进阶系列
控制台测试
Laravel 6 中文文档
测试系列
任务调度
Laravel 7 中文文档
进阶系列
任务调度
Laravel 8 中文文档
进阶系列
回到顶部
2022 基于 Laravel 6 构建
关于学院
订阅服务
友情链接
站点地图
本站 CDN 加速服务由又拍云赞助