Spanish (Español) translation by Rafael Chavarría (you can also view the original English article)



Si estás preguntando, "¿Qué es Yii?" revisa mi tutorial anterior: Introducción al Framework Yii, el cuál revisa los beneficios de Yii e incluye un vistazo general de qué hay de nuevo en Yii 2.0, liberado en Octubre de 2014.
En esta serie Programando Con Yii2, estoy guiando a los lectores en el uso del Framework Yii2 para PHP. En el tutorial de hoy, compartiré contigo como sacar ventaja de la capacidad de la consola de Yii para ejecutar trabajos cron.
En el pasado, he usado wget en mis trabajos cron---una URL accesible desde web ejecutaría mis tareas en segundo plano. Esto elevó los asuntos de seguridad y tiene algunos problemas de desempeño. Mientras que abordé algunas maneras de mitigar los riesgos en episodios de nuestra serie startup en seguridad, esperaba hacer transición a comandos llevados por consola. Y con Yii2 es bastante sencillo.
Para el ejemplo de hoy, demostraré comandos cron basados en consola en mi sitio Twixxtr el cuál describí en este episodio Twitter API. Debido a límites de taza y problemas de desempeño de administración, la API Twitter es muy dependiente de tareas cron eficientes y confiables. Así que es un gran ejemplo para compartir contigo.
Antes de que comience, reiteraré: siempre aprecio tus ideas y retroalimentación. Si tienes una pregunta o sugerencia de tema, por favor publica tus ideas en los comentarios de abajo. También puedes contactarme en Twitter @reifman directamente.
¿Qué Es Cron?
Wikipedia describe cron como "un programador de trabajos basado en tiempo en sistemas operativos computacionales parecidos a Unix." Y eso es bastante preciso. Básicamente, cron ejecuta todas las tareas en segundo plano que necesitamos para ejecutar servicios web, desde administración de registros y respaldos hasta peticiones API para limpieza de base de datos.
Para ver tus trabajos cron existentes en un servidor, usualmente tecleas sudo crontab -l
y ves algo como esto:
1 |
# Edit this file to introduce tasks to be run by cron.
|
2 |
#
|
3 |
# Each task to run has to be defined through a single line
|
4 |
# indicating with different fields when the task will be run
|
5 |
# and what command to run for the task
|
6 |
#
|
7 |
# To define the time you can provide concrete values for
|
8 |
# minute (m), hour (h), day of month (dom), month (mon),
|
9 |
# and day of week (dow) or use '*' in these fields (for 'any').#
|
10 |
# Notice that tasks will be started based on the cron's system
|
11 |
# daemon's notion of time and timezones.
|
12 |
#
|
13 |
# Output of the crontab jobs (including errors) is sent through
|
14 |
# email to the user the crontab file belongs to (unless redirected).
|
15 |
#
|
16 |
# For example, you can run a backup of all your user accounts
|
17 |
# at 5 a.m every week with:
|
18 |
# 0 5 * * 1 tar -zcf /var/backups/home.tgz /home/
|
19 |
#
|
20 |
# For more information see the manual pages of crontab(5) and cron(8)
|
21 |
#
|
22 |
# m h dom mon dow command
|
23 |
*/3 * * * * wget -O /dev/null https://meetingplanner.io/daemon/frequent |
24 |
*/15 * * * * wget -O /dev/null http://meetingplanner.io/daemon/quarter |
25 |
0 * * * * wget -O /dev/null http://meetingplanner.io/daemon/hourly |
26 |
15 1 * * * wget -O /dev/null http://meetingplanner.io/daemon/overnight |
27 |
40 2 * * * /usr/sbin/automysqlbackup |
28 |
15 3 * * 5 wget -O /dev/null http://meetingplanner.io/daemon/weekly |
29 |
30 2 * * 1 /opt/letsencrypt/letsencrypt-auto renew >> /var/log/le-renew.log |
El lado izquierdo especifica activar estas tareas cada 3 o 15 minutos o diariamente a media noche, etc., y el lado derecho es el script a ejecutar. Mira también Programando Tareas Con Trabajos Cron (Envato Tuts+).
Nota cómo el script Let's Encrypt es un comando de consola único. Este se ejecuta desde la línea de comando en nuestro servidor. Sin embargo, todas mis tareas de Planificador de Reuniones de arriba se ejecutan vía wget. Eso actúa como si un robot estuviera en un navegador web em un horario específico contra nuestra aplicación web que realiza tareas en segundo plano.
En adición a los gastos generales que una petición web externa requiere y las limitaciones de tiempo muerto en scripts en servidores, tienes que asegurar estos puntos de acceso. Aquí está un ejemplo de cómo lo hace Planificador de Reuniones:
1 |
// only cron jobs and admins can run this controller's actions
|
2 |
public function beforeAction($action) |
3 |
{
|
4 |
// your custom code here, if you want the code to run before action filters,
|
5 |
// which are triggered on the [[EVENT_BEFORE_ACTION]] event, e.g. PageCache or AccessControl
|
6 |
if (!parent::beforeAction($action)) { |
7 |
return false; |
8 |
}
|
9 |
// other custom code here
|
10 |
if (( $_SERVER['REMOTE_ADDR'] == $_SERVER['SERVER_ADDR'] ) || |
11 |
(!\Yii::$app->user->isGuest && \common\models\User::findOne(Yii::$app->user->getId())->isAdmin())) |
12 |
{
|
13 |
return true; |
14 |
}
|
15 |
return false; // or false to not run the action |
16 |
}
|
Este verifica que el usuario haya iniciado sesión como un administrador o ejecutando localmente en el servidor en una dirección IP de Internet idéntica.
Implementado Comandos Cron Basado en Consola
Alex Makarov, uno de los voluntarios líderes detrás del desarrollo del Framework Yii, ha sido de utilidad repondiéndome preguntas mientras escribo regularmente sobre el framework para Envato Tuts+. Después de leer mi episodio de seguridad, el preguntó por qué no estaba usando la capacidad de consola inherente de Yii2 para trabajos cron. Básicamente, yo no sabía de ella.
Así como tenía un /frontend/controllers/DaemonController.php, creé un /console/controllers/DaemonController.php. Para este tutorial, haré esto para el más pequeño y simple servicio web Twixxr.
Estoy acostumbrado a usar la consola para ejecutar migraciones de bases de datos (ej. ./yii migrate/up 7
), pero eso es todo. Estaba ansioso por probar usarlo para tareas en segundo plano.
Como lo escribí en un tutorial anterior, mi recién nacido sitio Twixxr requiere procesos extensivos en segundo plano para rotar regularmente llamadas API para todas las peticiones de usuario para ofrecer amistas a cuentas influyentes de Twitter pertenecientes a mujeres.
Aquí está cómo luce la página de inicio:



Así que pensé que Twixxr haría un gran lecho de prueba para ejecutar un controlador cron basado en consola.
El Nuevo DaemonController.php
Aquí está el núcleo de mi nuevo DaemonController.php basado en consola:
1 |
<?php
|
2 |
namespace console\controllers; |
3 |
|
4 |
use Yii; |
5 |
use yii\helpers\Url; |
6 |
use yii\console\Controller; |
7 |
use frontend\models\Twixxr; |
8 |
|
9 |
/**
|
10 |
* Test controller
|
11 |
*/
|
12 |
class DaemonController extends Controller { |
13 |
|
14 |
public function actionIndex() { |
15 |
echo "Yes, cron service is running."; |
16 |
}
|
17 |
|
18 |
public function actionFrequent() { |
19 |
// called every two minutes
|
20 |
// */2 * * * * ~/sites/www/yii2/yii test
|
21 |
$time_start = microtime(true); |
22 |
$x = new \frontend\models\Twixxr(); |
23 |
$x->process($time_start); |
24 |
$time_end = microtime(true); |
25 |
echo 'Processing for '.($time_end-$time_start).' seconds'; |
26 |
}
|
27 |
|
28 |
public function actionQuarter() { |
29 |
// called every fifteen minutes
|
30 |
$x = new \frontend\models\Twixxr(); |
31 |
$x->loadProfiles(); |
32 |
}
|
33 |
|
34 |
public function actionHourly() { |
35 |
// every hour
|
36 |
$current_hour = date('G'); |
37 |
if ($current_hour%4) { |
38 |
// every four hours
|
39 |
}
|
40 |
if ($current_hour%6) { |
41 |
// every six hours
|
42 |
}
|
43 |
}
|
Nota que es prácticamente idéntico a la estructura de mi controlador basado en front-end, pero es seguramente inaccesible a la web porque está en el árbol /console. Ningún servidor web Apache está configurado para navegar esta área.
Así qué, en el ejemplo de arriba, actionFrequent()
será llamado cada dos o tres minutos. Este procesa otro conjunto de peticiones de amistad Twixxr. Por otro lado, actionQuarter()
es llamado cada 15 minutos y actualiza la información de perfil para cuentas navegando. Veamos cómo funciona la programación en el archivo cron.
El Nuevo Archivo Crontab
Esencialmente, en mi archivo crontab, reemplazo wget con un script Linux directo como se muestra arriba para renovaciones Let's Encrypt.
Tecleas sudo crontab -e
para editar o -l
para listar sus contenidos. Aquí está mi archivo cron Twixxr:
1 |
$ sudo crontab -l |
2 |
# m h dom mon dow command
|
3 |
*/3 * * * * /var/www/twixxr/yii daemon/frequent |
4 |
*/15 * * * * /var/www/twixxr/yii daemon/quarter |
5 |
0 * * * * /var/www/twixxr/yii daemon/hourly |
6 |
15 1 * * * /var/www/twixxr/yii daemon/overnight |
7 |
15 3 * * 5 /var/www/twixxr/yii daemon/weekly |
8 |
#40 2 * * * /usr/sbin/automysqlbackup
|
9 |
30 2 * * 1 /usr/bin/letsencrypt renew >> /var/log/le-renew.log |
Es bastante simple. El lado izquierdo de /var/www/twixxr/yii daemon/frequent
es la ruta en donde vive el intérprete yii, y el lado derecho es el controlador y método de la consola a llamar.
Todo funcionó bastante bien cambiando. No he cambiado Planificador de Reuniones todavia ya que quiero hacer más pruebas. Cuando las tareas en segundo plano se quiebran, es difícil saberlo y depurarlas (aunque Sentry error logging está ayudando mucho).
Problemas a Considerar
Un elemento con el que me encontré es que el namespace de la consola es distinto al namespace del front-end--- así qué, por ejemplo, el componente SiteHelper.php que establecí en mi tutorial, que describió ejecutando múltiples sitios desde una sola base de código, falló cuando lo invoqué. Quitarlo funcionó, pero necesite ejecutar pruebas para asegurar que el código subyacente de fondo aún funcionaba. Sin embargo, la mayoría del intercambio salió bien.
Como con cualquier otro cambio de código, prueba y monitorea a fondo.
Qué Sigue
Viendo hacia adelante, exploraré construir APIs REST dentro del framework Yii2, el cuál depende coincidentemente en crear un sub-árbol distinto como el árbol de consola pero para APIs externas. Por supuesto, esto trae problemas complejos de autenticación y seguridad... así que será divertido explorar estos contigo. Estaré viendo APIs desde varios ángulos. Estoy en realidad bastante emocionado sobre esto.
Espera los siguientes tutoriales en mi serie Programando Con Yii2 mientras continuo sumergiéndome en diferentes aspectos del framework. Por favor también explora la serie Construyendo Tu Startup Con PHP, que documento el proceso de construir Simple Planner y Planificador de Reuniones.
Si quisieras saber cuando llega el siguiente tutorial Yii2, sígueme en Twitter @reifman o revisa mi página de instructor para actualizaciones.
Enlaces Relacionados
- Intercambio de Desarrollador Yii2, mi sitio de recursos Yii2
- Programando Tareas Con Trabajos Cron (Envato Tuts+)
- Cómo implementar cron en Yii2 (Documentación Yii)
- Twixxr, el servicio web de muestra que mencioné