如果您问“Yii 是什么?”查看我之前的教程:Yii 框架简介,其中回顾了 Yii 的优点,并概述了 2014 年 10 月发布的 Yii 2.0 的新增功能。嗯>
在这个使用 Yii2 编程系列中,我将指导读者使用 Yii2 PHP 框架。在今天的教程中,我将与您分享如何利用 Yii 的控制台功能来运行 cron 作业。
过去,我在 cron 作业中使用了 wget — 可通过 Web 访问的 URL 来运行我的后台任务。这引发了安全问题并存在一些性能问题。虽然我在我们的启动系列安全性专题中讨论了一些减轻风险的方法,但我曾希望过渡到控制台驱动的命令。对于 Yii2 来说,这相当简单。
对于今天的示例,我将在我的 Twixxr 站点上演示基于控制台的 cron 命令,我在本 Twitter API 剧集中对此进行了描述。由于速率限制和性能管理问题,Twitter API 非常依赖高效、可靠的 cron 任务。所以这是一个很好的例子,可以与您分享。
在开始之前,我要重申:我始终感谢您的想法和反馈。如果您有问题或主题建议,请在下面的评论中发表您的想法。您也可以直接通过 Twitter @reifman 联系我。
什么是 Cron?
维基百科将 cron 描述为“类 Unix 计算机操作系统中基于时间的作业调度程序”。这是相当准确的。基本上,cron 运行我们运行 Web 服务所需的所有后台任务,从日志管理和备份到 API 请求再到数据库清理。
要查看服务器上现有的 cron 作业,您通常输入 sudo crontab -l
并看到如下内容:
# Edit this file to introduce tasks to be run by cron. # # Each task to run has to be defined through a single line # indicating with different fields when the task will be run # and what command to run for the task # # To define the time you can provide concrete values for # minute (m), hour (h), day of month (dom), month (mon), # and day of week (dow) or use '*' in these fields (for 'any').# # Notice that tasks will be started based on the cron's system # daemon's notion of time and timezones. # # Output of the crontab jobs (including errors) is sent through # email to the user the crontab file belongs to (unless redirected). # # For example, you can run a backup of all your user accounts # at 5 a.m every week with: # 0 5 * * 1 tar -zcf /var/backups/home.tgz /home/ # # For more information see the manual pages of crontab(5) and cron(8) # # m h dom mon dow command */3 * * * * wget -O /dev/null https://meetingplanner.io/daemon/frequent */15 * * * * wget -O /dev/null http://meetingplanner.io/daemon/quarter 0 * * * * wget -O /dev/null http://meetingplanner.io/daemon/hourly 15 1 * * * wget -O /dev/null http://meetingplanner.io/daemon/overnight 40 2 * * * /usr/sbin/automysqlbackup 15 3 * * 5 wget -O /dev/null http://meetingplanner.io/daemon/weekly 30 2 * * 1 /opt/letsencrypt/letsencrypt-auto renew >> /var/log/le-renew.log
左侧指定每 3 或 15 分钟或每天午夜等激活这些任务,右侧是要运行的脚本。 另请参阅使用 Cron 作业安排任务 (Envato Tuts+)。
请注意 Let’s Encrypt 脚本是一个独特的控制台命令。它从我们服务器上的命令行运行。但是,我上面的所有会议计划任务都是通过 wget 运行的。这就像一个机器人在特定时间在网络浏览器上运行针对我们执行后台任务的网络应用程序的请求。
除了外部 Web 请求所需的开销和服务器上脚本的超时限制之外,您还必须保护这些访问点。以下是会议策划者如何执行此操作的示例:
// only cron jobs and admins can run this controller's actions public function beforeAction($action) { // your custom code here, if you want the code to run before action filters, // which are triggered on the [[EVENT_BEFORE_ACTION]] event, e.g. PageCache or AccessControl if (!parent::beforeAction($action)) { return false; } // other custom code here if (( $_SERVER['REMOTE_ADDR'] == $_SERVER['SERVER_ADDR'] ) || (!/Yii::$app->user->isGuest && /common/models/User::findOne(Yii::$app->user->getId())->isAdmin())) { return true; } return false; // or false to not run the action }
它验证用户是否以管理员身份登录或以相同的 Internet IP 地址在服务器上本地运行。
实现基于控制台的 Cron 命令
Alex Makarov 是 Yii 框架开发的主要志愿者之一,当我定期撰写有关 Envato Tuts+ 框架的文章时,他帮助回答了我的问题。读完我的安全事件后,他问我为什么不使用 Yii2 固有的控制台功能来执行 cron 作业。基本上我不知道。
就像我有一个 /frontend/controllers/DaemonController.php 一样,我创建了一个 /console/controllers/DaemonController.php。在本教程中,我将为更小、更简单的 Twixxr Web 服务执行此操作。
我习惯使用控制台运行数据库迁移(例如 ./yii migrate/up 7
),但仅此而已。我很想尝试使用它来执行后台任务。
正如我在之前的教程中所写的,我的新生网站 Twixxr 需要大量的后台进程来定期轮换 API 调用,以满足所有用户请求,以与女性拥有的有影响力的 Twitter 帐户交友。
主页如下所示:
所以我认为 Twixxr 会成为运行基于控制台的 cron 控制器的一个很好的测试平台。
新的 DaemonController.php
这是我的新的基于控制台的 DaemonController.php 的核心:
<?php namespace console/controllers; use Yii; use yii/helpers/Url; use yii/console/Controller; use frontend/models/Twixxr; /** * Test controller */ class DaemonController extends Controller { public function actionIndex() { echo "Yes, cron service is running."; } public function actionFrequent() { // called every two minutes // */2 * * * * ~/sites/www/yii2/yii test $time_start = microtime(true); $x = new /frontend/models/Twixxr(); $x->process($time_start); $time_end = microtime(true); echo 'Processing for '.($time_end-$time_start).' seconds'; } public function actionQuarter() { // called every fifteen minutes $x = new /frontend/models/Twixxr(); $x->loadProfiles(); } public function actionHourly() { // every hour $current_hour = date('G'); if ($current_hour%4) { // every four hours } if ($current_hour%6) { // every six hours } }
请注意,它与我的基于前端的控制器的结构非常相似,但它无法安全地通过网络访问,因为它位于 /console 树中。没有配置 Apache 网络服务器站点来浏览此区域。
因此,在上面的示例中,actionFrequent()
将每两到三分钟调用一次。它处理另一组 Twixxr 友谊请求。另一方面,actionQuarter()
每 15 分钟调用一次,并更新浏览帐户的配置文件信息。让我们看看 cron 文件中的计划是如何工作的。
新的 crontab 文件
本质上,在我的 crontab 文件中,我将 wget 替换为直接 Linux 脚本,如上所示,用于 Let’s Encrypt 续订。
您输入 sudo crontab -e
进行编辑,或输入 -l
列出其内容。这是我的 Twixxr cron 文件:
$ sudo crontab -l # m h dom mon dow command */3 * * * * /var/www/twixxr/yii daemon/frequent */15 * * * * /var/www/twixxr/yii daemon/quarter 0 * * * * /var/www/twixxr/yii daemon/hourly 15 1 * * * /var/www/twixxr/yii daemon/overnight 15 3 * * 5 /var/www/twixxr/yii daemon/weekly #40 2 * * * /usr/sbin/automysqlbackup 30 2 * * 1 /usr/bin/letsencrypt renew >> /var/log/le-renew.log
这非常简单。 /var/www/twixxr/yii daemon/frequent
的左侧是 yii 解释器所在的路径,右侧是控制台控制器和调用的方法。 p>
切换时一切都很顺利。我还没有切换 Meeting Planner,因为我想做更多测试。当后台任务中断时,很难知道也很难调试它们(尽管 Sentry 错误日志记录有很大帮助)。
需要考虑的问题
我遇到的一个问题是控制台命名空间与前端命名空间不同,因此,例如,我在教程中设置的 SiteHelper.php 组件(该组件描述了从单个代码库运行多个网站)失败了当我调用它时。删除它是有效的,但我需要运行测试以确保底层后台代码仍然有效。不过,大部分情况下切换都很顺利。
与任何其他代码更改一样,彻底测试和监控。
下一步是什么
展望未来,我将探索在 Yii2 框架内构建 REST API,该框架恰好依赖于创建一个不同的子树,例如控制台树,但用于外部 API。当然,这会带来复杂的身份验证和安全问题……所以与您一起探索这些将会很有趣。我将从多个角度研究 API。我对此感到非常兴奋。
请观看我的“使用 Yii2 编程”系列中即将推出的教程,我将继续深入研究该框架的不同方面。另请浏览“使用 PHP 构建您的初创公司”系列,其中记录了构建 Simple Planner 和 Meeting Planner 的过程。
如果您想知道下一个 Yii2 教程何时发布,请在 Twitter 上关注我 @reifman 或查看我的讲师页面以获取更新。
相关链接
- Yii2 Developer Exchange,我的 Yii2 资源站点
- 使用 Cron 作业安排任务 (Envato Tuts+)
- 如何在 Yii2 中实现 cron(Yii 文档)
- Twixxr,其中提到的示例网络服务
以上就是Yii2编程指南:运行Cron服务的方法的详细内容,更多请关注php中文网其它相关文章!