Если вы спрашиваете: «Что такое Yii?» Посмотрите мой предыдущий учебник: Введение в Yii Framework , который рассматривает преимущества Yii и включает обзор того, что нового в Yii 2.0, выпущенном в октябре 2014 года.
В этой серии «Программирование с Yii2» я расскажу читателям, как использовать Yii2 Framework для PHP. В сегодняшнем уроке я расскажу вам, как использовать возможности консоли Yii для выполнения заданий cron.
В прошлом я использовал wget в своих заданиях cron — доступный через Интернет URL-адрес запускал мои фоновые задачи. Это подняло проблемы безопасности и имеет некоторые проблемы с производительностью. Хотя я рассмотрел некоторые способы снижения рисков в эпизодах, посвященных безопасности , в нашей серии стартапов , я надеялся перейти на консольные команды. А с Yii2 это довольно просто.
Для сегодняшнего примера я продемонстрирую консольные команды cron на своем сайте Twixxr, которые я описал в этом эпизоде Twitter API . Из-за ограничений скорости и проблем с управлением производительностью API Twitter очень сильно зависит от эффективных и надежных задач cron. Так что это отличный пример, чтобы поделиться с вами.
Прежде чем начать, еще раз повторю: я всегда благодарен за ваши идеи и отзывы. Если у вас есть вопрос или предложение по теме, пожалуйста, оставьте свои мысли в комментариях ниже. Вы также можете связаться со мной через Twitter @reifman напрямую.
Что такое Крон?
Википедия описывает cron как «основанный на времени планировщик заданий в Unix-подобных компьютерных операционных системах». И это довольно точно. По сути, cron выполняет все фоновые задачи, которые нам нужны для запуска веб-сервисов, от управления журналами и резервного копирования до запросов API и очистки базы данных.
Чтобы увидеть ваши существующие задания cron на сервере, вы обычно sudo crontab -l
и видите что-то вроде этого:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
# 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 am 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)
#
# mh dom mon dow command
*/3 * * * * wget -O /dev/null http://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 Jobs (Envato Tuts +) .
Обратите внимание, что скрипт Let’s Encrypt является уникальной консольной командой. Он запускается из командной строки на нашем сервере. Тем не менее, все мои задачи планировщика собраний выполняются через wget . Это действует так, как если бы робот в определенное время находился в веб-браузере и выполнял запросы к нашему веб-приложению, которое выполняет фоновые задачи.
В дополнение к накладным расходам, которые требует внешний веб-запрос, и ограничения времени ожидания для сценариев на серверах, вам необходимо защитить эти точки доступа. Вот пример того, как Meeting Planner делает это:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
|
// 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, eg 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;
}
|
Он проверяет, что пользователь вошел в систему как администратор или работает локально на сервере с идентичным IP-адресом в Интернете.
Реализация команд Cron на основе консоли
Алекс Макаров , один из ведущих волонтеров в разработке Yii Framework, помог мне ответить на вопросы, так как я регулярно пишу о среде для Envato Tuts +. Прочитав мой эпизод по безопасности, он спросил, почему я не использовал встроенную в Yii2 консольную функцию для задач cron. По сути, я не знал об этом.
Так же, как у меня был /frontend/controllers/DaemonController.php, я создал /console/controllers/DaemonController.php. В этом уроке я сделаю это для меньшего, более простого веб-сервиса Twixxr .
Я привык использовать консоль для запуска миграции баз данных (например ./yii migrate/up 7
), но это все. Я был готов попробовать использовать его для фоновых задач.
Как я уже писал в предыдущем уроке , моему новорожденному сайту Twixxr требуются обширные фоновые процессы для регулярной ротации вызовов API для всех пользовательских запросов, чтобы подружиться с влиятельными учетными записями Twitter, которыми владеют женщины.
Вот как выглядит домашняя страница:
Поэтому я подумал, что Twixxr станет отличным испытательным стендом для запуска консольного контроллера cron.
Новый DaemonController.php
Вот ядро моего нового консольного DaemonController.php:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
|
<?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).’
}
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
для просмотра его содержимого. Вот мой файл cron Twixxr:
1
2
3
4
5
6
7
8
9
|
$ sudo crontab -l
# mh 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, а правая часть — контроллер консоли и вызываемый метод.
Все работало довольно хорошо переключаясь. Я еще не включил Meeting Planner, так как хочу больше тестировать. Когда фоновые задачи ломаются, их сложно узнать и отладить (хотя регистрация ошибок Sentry очень помогает).
Вопросы для рассмотрения
Один элемент, с которым я столкнулся, заключается в том, что пространство имен консоли отличается от внешнего пространства имен — поэтому, например, компонент SiteHelper.php, который я настроил в своем учебном пособии, в котором описывается запуск нескольких сайтов из одной кодовой базы , завершился неудачно при вызове Это. Удаление работало, но мне нужно было запустить тесты, чтобы убедиться, что основной фоновый код все еще функционирует. Тем не менее, в основном переключение прошло гладко.
Как и при любом другом изменении кода, тщательно проверяйте и отслеживайте.
Что дальше
Забегая вперёд, я рассмотрю создание API REST в Yii2 Framework, которое по совпадению основывается на создании отдельного поддерева, такого как дерево консоли, но для внешних API. Конечно, это вызывает сложные вопросы аутентификации и безопасности … так что будет интересно изучить их вместе с вами. Я буду смотреть на API с нескольких точек зрения. Я на самом деле очень рад этому.
Следите за будущими уроками в моей серии «Программирование с Yii2», поскольку я продолжаю изучать различные аспекты фреймворка. Также ознакомьтесь с серией « Построение стартапа с помощью PHP» , в которой описывается процесс создания Simple Planner и Meeting Planner .
Если вы хотите узнать, когда появится следующий учебник по Yii2, следуйте за мной @reifman в Твиттере или зайдите на страницу моего инструктора для получения обновлений.
Ссылки по теме
- Yii2 Developer Exchange , мой ресурсный сайт Yii2
- Планирование задач с помощью Cron Jobs (Envato Tuts +)
- Как реализовать cron в Yii2 (Документация Yii)
- Twixxr , пример веб-службы, упомянутой в