Laravel Horizon
- Introducción
- Instalación
- Actualizando Horizon
- Ejecutando Horizon
- Etiquetas
- Notificaciones
- Métricas
- Eliminando Trabajos Fallidos
- Limpiando Trabajos de Colas
Introducción
[!NOTE] Antes de adentrarte en Laravel Horizon, debes familiarizarte con los servicios de cola básicos de Laravel. Horizon complementa la cola de Laravel con características adicionales que pueden ser confusas si no estás ya familiarizado con las funciones de cola básicas que ofrece Laravel. Laravel Horizon proporciona un hermoso panel y configuración basada en código para tus colas Redis impulsadas por Laravel. Horizon te permite monitorear fácilmente métricas clave de tu sistema de colas, como el rendimiento de trabajos, tiempo de ejecución y fallos de trabajos. Cuando uses Horizon, toda la configuración de tus trabajadores de cola se almacena en un solo archivo de configuración simple. Al definir la configuración de los trabajadores de tu aplicación en un archivo controlado por versión, puedes escalar o modificar fácilmente los trabajadores de cola de tu aplicación al desplegar tu aplicación.
Instalación
[!WARNING] Laravel Horizon requiere que utilices Redis para gestionar tu cola. Por lo tanto, debes asegurarte de que tu conexión de cola esté configurada en
redis
en el archivo de configuraciónconfig/queue.php
de tu aplicación. Puedes instalar Horizon en tu proyecto utilizando el gestor de paquetes Composer:
composer require laravel/horizon
Después de instalar Horizon, publica sus activos utilizando el comando Artisan horizon:install
:
php artisan horizon:install
Configuración
Después de publicar los activos de Horizon, su archivo de configuración principal se ubicará en config/horizon.php
. Este archivo de configuración te permite configurar las opciones del trabajador de cola para tu aplicación. Cada opción de configuración incluye una descripción de su propósito, así que asegúrate de explorar a fondo este archivo.
[!WARNING] Horizon utiliza internamente una conexión Redis llamada
horizon
. Este nombre de conexión Redis está reservado y no debe asignarse a otra conexión Redis en el archivo de configuracióndatabase.php
o como el valor de la opciónuse
en el archivo de configuraciónhorizon.php
.
Entornos
Después de la instalación, la opción de configuración principal de Horizon con la que debes familiarizarte es la opción de configuración environments
. Esta opción de configuración es un array de entornos en los que se ejecuta tu aplicación y define las opciones del proceso de trabajo para cada entorno. Por defecto, esta entrada contiene un entorno production
y local
. Sin embargo, puedes añadir más entornos según sea necesario:
'environments' => [ 'production' => [ 'supervisor-1' => [ 'maxProcesses' => 10, 'balanceMaxShift' => 1, 'balanceCooldown' => 3, ], ], 'local' => [ 'supervisor-1' => [ 'maxProcesses' => 3, ], ],],
También puedes definir un entorno comodín (*
) que se usará cuando no se encuentre otro entorno coincidente:
'environments' => [ // ... '*' => [ 'supervisor-1' => [ 'maxProcesses' => 3, ], ],],
Cuando inicias Horizon, utilizará las opciones de configuración del proceso de trabajo para el entorno en el que se está ejecutando tu aplicación. Típicamente, el entorno se determina por el valor de la variable de entorno APP_ENV
variable de entorno. Por ejemplo, el entorno local
de Horizon por defecto está configurado para iniciar tres procesos de trabajo y equilibrar automáticamente el número de procesos de trabajo asignados a cada cola. El entorno production
por defecto está configurado para iniciar un máximo de 10 procesos de trabajo y equilibrar automáticamente el número de procesos de trabajo asignados a cada cola.
[!WARNING] Debes asegurarte de que la porción
environments
de tu archivo de configuraciónhorizon
contenga una entrada para cada entorno en el que planeas ejecutar Horizon.
Supervisores
Como puedes ver en el archivo de configuración predeterminado de Horizon, cada entorno puede contener uno o más "supervisores". Por defecto, el archivo de configuración define este supervisor como supervisor-1
; sin embargo, puedes nombrar a tus supervisores como desees. Cada supervisor es esencialmente responsable de "supervisar" un grupo de procesos de trabajo y se encarga de equilibrar los procesos de trabajo entre las colas.
Puedes añadir supervisores adicionales a un entorno dado si deseas definir un nuevo grupo de procesos de trabajo que deben ejecutarse en ese entorno. Puedes elegir hacer esto si deseas definir una estrategia de balanceo diferente o un conteo de procesos de trabajo para una cola dada utilizada por tu aplicación.
Modo de Mantenimiento
Mientras tu aplicación esté en modo de mantenimiento, los trabajos en cola no serán procesados por Horizon a menos que la opción force
del supervisor esté definida como true
dentro del archivo de configuración de Horizon:
'environments' => [ 'production' => [ 'supervisor-1' => [ // ... 'force' => true, ], ],],
Valores Predeterminados
Dentro del archivo de configuración predeterminado de Horizon, notarás una opción de configuración defaults
. Esta opción de configuración especifica los valores predeterminados para los supervisores de tu aplicación. Los valores de configuración predeterminados del supervisor se combinarán en la configuración del supervisor para cada entorno, lo que te permitirá evitar repeticiones innecesarias al definir tus supervisores.
Estrategias de Balanceo
A diferencia del sistema de cola predeterminado de Laravel, Horizon te permite elegir entre tres estrategias de balanceo de trabajadores: simple
, auto
y false
. La estrategia simple
divide los trabajos entrantes de manera uniforme entre los procesos de trabajo:
'balance' => 'simple',
La estrategia auto
, que es la predeterminada del archivo de configuración, ajusta el número de procesos de trabajo por cola en función de la carga de trabajo actual de la cola. Por ejemplo, si tu cola notifications
tiene 1,000 trabajos pendientes mientras que tu cola render
está vacía, Horizon asignará más trabajadores a tu cola notifications
hasta que la cola esté vacía.
Al utilizar la estrategia auto
, puedes definir las opciones de configuración minProcesses
y maxProcesses
para controlar el número mínimo de procesos por cola y el número máximo de procesos de trabajo en total a los que Horizon debe escalar hacia arriba y hacia abajo:
'environments' => [ 'production' => [ 'supervisor-1' => [ 'connection' => 'redis', 'queue' => ['default'], 'balance' => 'auto', 'autoScalingStrategy' => 'time', 'minProcesses' => 1, 'maxProcesses' => 10, 'balanceMaxShift' => 1, 'balanceCooldown' => 3, 'tries' => 3, ], ],],
El valor de configuración autoScalingStrategy
determina si Horizon asignará más procesos de trabajo a las colas en función del tiempo total que llevará limpiar la cola (estrategia time
) o por el número total de trabajos en la cola (estrategia size
).
Los valores de configuración balanceMaxShift
y balanceCooldown
determinan cuán rápido escalará Horizon para satisfacer la demanda de los trabajadores. En el ejemplo anterior, se crearán o destruirán un máximo de un nuevo proceso cada tres segundos. Puedes ajustar estos valores según sea necesario en función de las necesidades de tu aplicación.
Cuando la opción balance
está configurada en false
, se utilizará el comportamiento predeterminado de Laravel, en el que las colas se procesan en el orden en que están listadas en tu configuración.
Autorización del Dashboard
El panel de Horizon se puede acceder a través de la ruta /horizon
. Por defecto, solo podrás acceder a este panel en el entorno local
. Sin embargo, dentro de tu archivo app/Providers/HorizonServiceProvider.php
, hay una definición de puerta de autorización. Esta puerta de autorización controla el acceso a Horizon en entornos no locales. Puedes modificar esta puerta según sea necesario para restringir el acceso a tu instalación de Horizon:
/** * Register the Horizon gate. * * This gate determines who can access Horizon in non-local environments. */protected function gate(): void{ Gate::define('viewHorizon', function (User $user) { return in_array($user->email, [ 'taylor@laravel.com', ]); });}
Estrategias de Autenticación Alternativas
Recuerda que Laravel inyecta automáticamente al usuario autenticado en la función anónima de la puerta de acceso. Si tu aplicación está proporcionando seguridad de Horizon a través de otro método, como restricciones de IP, entonces tus usuarios de Horizon pueden no necesitar "iniciar sesión". Por lo tanto, necesitarás cambiar la firma de la función anónima function (User $user)
arriba a function (User $user = null)
para obligar a Laravel a no requerir autenticación.
Trabajos Silenciados
A veces, es posible que no estés interesado en ver ciertos trabajos despachados por tu aplicación o paquetes de terceros. En lugar de que estos trabajos ocupen espacio en tu lista de "Trabajos Completados", puedes silenciarlos. Para comenzar, añade el nombre de la clase del trabajo a la opción de configuración silenced
en el archivo de configuración horizon
de tu aplicación:
'silenced' => [ App\Jobs\ProcessPodcast::class,],
Alternativamente, el trabajo que deseas silenciar puede implementar la interfaz Laravel\Horizon\Contracts\Silenced
. Si un trabajo implementa esta interfaz, se silenciará automáticamente, incluso si no está presente en el array de configuración silenced
:
use Laravel\Horizon\Contracts\Silenced; class ProcessPodcast implements ShouldQueue, Silenced{ use Queueable; // ...}
Actualizando Horizon
Al actualizar a una nueva versión mayor de Horizon, es importante que revises cuidadosamente la guía de actualización.
Ejecutando Horizon
Una vez que hayas configurado tus supervisores y trabajadores en el archivo de configuración config/horizon.php
de tu aplicación, puedes iniciar Horizon utilizando el comando Artisan horizon
. Este único comando iniciará todos los procesos de trabajo configurados para el entorno actual:
php artisan horizon
Puedes pausar el proceso de Horizon e indicarle que continúe procesando trabajos utilizando los comandos Artisan horizon:pause
y horizon:continue
:
php artisan horizon:pause php artisan horizon:continue
También puedes pausar y continuar supervisores específicos de Horizon supervisores utilizando los comandos Artisan horizon:pause-supervisor
y horizon:continue-supervisor
:
php artisan horizon:pause-supervisor supervisor-1 php artisan horizon:continue-supervisor supervisor-1
Puedes verificar el estado actual del proceso de Horizon utilizando el comando Artisan horizon:status
:
php artisan horizon:status
Puedes finalizar el proceso de Horizon de forma elegante utilizando el comando Artisan horizon:terminate
. Cualquier trabajo que se esté procesando actualmente se completará y luego Horizon dejará de ejecutarse:
Desplegando Horizon
Cuando estés listo para implementar Horizon en el servidor real de tu aplicación, deberías configurar un monitor de procesos para supervisar el comando php artisan horizon
y reiniciarlo si sale inesperadamente. No te preocupes, discutiremos cómo instalar un monitor de procesos a continuación.
Durante el proceso de despliegue de tu aplicación, debes instruir al proceso de Horizon a que se termine para que sea reiniciado por tu monitor de procesos y reciba tus cambios de código:
php artisan horizon:terminate
Instalando Supervisor
Supervisor es un monitor de procesos para el sistema operativo Linux y reiniciará automáticamente tu proceso horizon
si deja de ejecutarse. Para instalar Supervisor en Ubuntu, puedes usar el siguiente comando. Si no estás utilizando Ubuntu, probablemente puedas instalar Supervisor utilizando el administrador de paquetes de tu sistema operativo:
sudo apt-get install supervisor
[!NOTA] Si configurar Supervisor tú mismo te parece abrumador, considera usar Laravel Forge, que instalará y configurará Supervisor automáticamente para tus proyectos Laravel.
Configuración del Supervisor
Los archivos de configuración de Supervisor se almacenan típicamente en el directorio /etc/supervisor/conf.d
de tu servidor. Dentro de este directorio, puedes crear cualquier número de archivos de configuración que indiquen a Supervisor cómo se deben monitorear tus procesos. Por ejemplo, vamos a crear un archivo horizon.conf
que inicie y monitoree un proceso horizon
:
[program:horizon]process_name=%(program_name)scommand=php /home/forge/example.com/artisan horizonautostart=trueautorestart=trueuser=forgeredirect_stderr=truestdout_logfile=/home/forge/example.com/horizon.logstopwaitsecs=3600
Al definir la configuración de tu Supervisor, debes asegurarte de que el valor de stopwaitsecs
sea mayor que el número de segundos consumidos por tu trabajo de mayor duración. De lo contrario, Supervisor puede matar el trabajo antes de que haya terminado de procesar.
[!WARNING] Aunque los ejemplos anteriores son válidos para servidores basados en Ubuntu, la ubicación y la extensión de archivo que se espera de los archivos de configuración de Supervisor pueden variar entre otros sistemas operativos de servidor. Consulta la documentación de tu servidor para obtener más información.
Iniciando Supervisor
Una vez que se ha creado el archivo de configuración, puedes actualizar la configuración del Supervisor y comenzar los procesos monitorizados utilizando los siguientes comandos:
sudo supervisorctl reread sudo supervisorctl update sudo supervisorctl start horizon
[!NOTE] Para obtener más información sobre cómo ejecutar Supervisor, consulta la documentación de Supervisor.
Etiquetas
Horizon te permite asignar “etiquetas” a trabajos, incluidos mailables, eventos de transmisión, notificaciones y oyentes de eventos en cola. De hecho, Horizon etiquetará de manera inteligente y automática la mayoría de los trabajos según los modelos Eloquent que están adjuntos al trabajo. Por ejemplo, echa un vistazo al siguiente trabajo:
<?php namespace App\Jobs; use App\Models\Video;use Illuminate\Contracts\Queue\ShouldQueue;use Illuminate\Foundation\Queue\Queueable; class RenderVideo implements ShouldQueue{ use Queueable; /** * Create a new job instance. */ public function __construct( public Video $video, ) {} /** * Execute the job. */ public function handle(): void { // ... }}
Si este trabajo está en cola con una instancia de App\Models\Video
que tiene un atributo id
de 1
, recibirá automáticamente la etiqueta App\Models\Video:1
. Esto se debe a que Horizon buscará las propiedades del trabajo para encontrar cualquier modelo Eloquent. Si se encuentran modelos Eloquent, Horizon etiquetará de manera inteligente el trabajo utilizando el nombre de la clase del modelo y la clave primaria:
use App\Jobs\RenderVideo;use App\Models\Video; $video = Video::find(1); RenderVideo::dispatch($video);
Etiquetando Jobs Manualmente
Si deseas definir manualmente las etiquetas para uno de tus objetos en cola, puedes definir un método tags
en la clase:
class RenderVideo implements ShouldQueue{ /** * Get the tags that should be assigned to the job. * * @return array<int, string> */ public function tags(): array { return ['render', 'video:'.$this->video->id]; }}
Etiquetado Manual de Escuchas de Eventos
Al recuperar las etiquetas para un listener de eventos en cola, Horizon pasará automáticamente la instancia del evento al método tags
, lo que te permitirá agregar datos del evento a las etiquetas:
class SendRenderNotifications implements ShouldQueue{ /** * Get the tags that should be assigned to the listener. * * @return array<int, string> */ public function tags(VideoRendered $event): array { return ['video:'.$event->video->id]; }}
Notificaciones
[!WARNING] Al configurar Horizon para enviar notificaciones de Slack o SMS, debes revisar los requisitos previos para el canal de notificación relevante. Si deseas ser notificado cuando una de tus colas tiene un tiempo de espera largo, puedes usar los métodos
Horizon::routeMailNotificationsTo
,Horizon::routeSlackNotificationsTo
yHorizon::routeSmsNotificationsTo
. Puedes llamar a estos métodos desde el métodoboot
delApp\Providers\HorizonServiceProvider
de tu aplicación:
/** * Bootstrap any application services. */public function boot(): void{ parent::boot(); Horizon::routeSmsNotificationsTo('15556667777'); Horizon::routeMailNotificationsTo('example@example.com'); Horizon::routeSlackNotificationsTo('slack-webhook-url', '#channel');}
Configurando Umbrales de Tiempo de Espera para Notificaciones
Puedes configurar cuántos segundos se consideran una "espera larga" dentro del archivo de configuración config/horizon.php
de tu aplicación. La opción de configuración waits
dentro de este archivo te permite controlar el umbral de espera larga para cada combinación de conexión / cola. Cualquier combinación de conexión / cola no definida tendrá por defecto un umbral de espera larga de 60 segundos:
'waits' => [ 'redis:critical' => 30, 'redis:default' => 60, 'redis:batch' => 120,],
Métricas
Horizon incluye un panel de métricas que proporciona información sobre los tiempos de espera de tus trabajos y colas, así como el rendimiento. Para rellenar este panel, debes configurar el comando Artisan snapshot
de Horizon para que se ejecute cada cinco minutos en el archivo routes/console.php
de tu aplicación:
use Illuminate\Support\Facades\Schedule; Schedule::command('horizon:snapshot')->everyFiveMinutes();
Eliminando Trabajos Fallidos
Si deseas eliminar un trabajo fallido, puedes usar el comando horizon:forget
. El comando horizon:forget
acepta la ID o UUID del trabajo fallido como su único argumento:
php artisan horizon:forget 5
Si deseas eliminar todos los trabajos fallidos, puedes proporcionar la opción --all
al comando horizon:forget
:
php artisan horizon:forget --all
Limpiando Trabajos de las Colas
Si deseas eliminar todos los trabajos de la cola predeterminada de tu aplicación, puedes hacerlo utilizando el comando Artisan horizon:clear
:
php artisan horizon:clear
Puedes proporcionar la opción queue
para eliminar trabajos de una cola específica:
php artisan horizon:clear --queue=emails