Horizon: monitoramento de filas no Laravel

1. Introdução ao Laravel Horizon

O Laravel Horizon é uma ferramenta oficial do ecossistema Laravel projetada para gerenciar e monitorar filas de processamento assíncrono com Redis. Diferentemente do sistema tradicional de filas do Laravel (Queue), que depende de workers baseados em processos simples, o Horizon oferece uma interface visual rica, métricas em tempo real e um sistema de balanceamento inteligente de workers.

Enquanto as filas tradicionais exigem que o desenvolvedor monitore manualmente os processos e gerencie falhas, o Horizon automatiza grande parte desse trabalho, fornecendo um dashboard onde é possível visualizar jobs pendentes, falhos, throughput e tempo de execução. A principal diferença está na arquitetura: o Horizon utiliza o Redis como backend, permitindo operações mais rápidas e escaláveis.

Os requisitos mínimos para instalação incluem PHP 8.0 ou superior, Laravel 8 ou superior e, obrigatoriamente, o Redis configurado como driver de fila. O Horizon não funciona com outros drivers como database ou SQS.

2. Instalação e Configuração Inicial

Para instalar o Horizon, utilize o Composer:

composer require laravel/horizon

Após a instalação, publique os assets e a configuração:

php artisan horizon:install

Isso criará o arquivo config/horizon.php e os assets necessários. O arquivo de configuração contém seções para diferentes ambientes:

'environments' => [
    'production' => [
        'supervisor-1' => [
            'connection' => 'redis',
            'queue' => ['default'],
            'balance' => 'auto',
            'processes' => 10,
            'tries' => 3,
        ],
    ],

    'local' => [
        'supervisor-1' => [
            'connection' => 'redis',
            'queue' => ['default'],
            'balance' => 'simple',
            'processes' => 3,
            'tries' => 1,
        ],
    ],
],

No ambiente local, usamos balance como simple com poucos processos. Em produção, auto permite que o Horizon gerencie dinamicamente a distribuição de workers entre filas.

3. Gerenciamento de Workers e Filas

O Horizon organiza workers através de supervisors, que são grupos de processos responsáveis por executar jobs de filas específicas. Cada supervisor pode ser configurado com diferentes estratégias de balanceamento.

A configuração de balanceamento é crucial para aplicações com múltiplas filas de prioridades diferentes:

'supervisor-1' => [
    'connection' => 'redis',
    'queue' => ['high', 'default', 'low'],
    'balance' => 'auto',
    'processes' => 20,
    'tries' => 3,
    'minProcesses' => 5,
    'maxProcesses' => 30,
    'balanceMaxShift' => 5,
    'balanceCooldown' => 3,
],

Nesse exemplo, definimos três filas com prioridades implícitas (a ordem no array determina a prioridade). O balanceMaxShift controla quantos processos podem ser movidos entre filas por vez, enquanto balanceCooldown define o intervalo entre rebalanceamentos.

O auto-escalonamento permite que o Horizon aumente ou diminua o número de workers baseado na carga atual, otimizando o uso de recursos.

4. Monitoramento em Tempo Real com o Dashboard

O dashboard do Horizon fica acessível na rota /horizon após a instalação. Para proteger o acesso em produção, registre o service provider no arquivo config/app.php:

'providers' => [
    // ...
    App\Providers\HorizonServiceProvider::class,
],

No dashboard, você encontra:

  • Jobs pendentes: fila atual de jobs aguardando processamento
  • Jobs falhos: lista de jobs que excederam o número de tentativas
  • Throughput: gráfico de jobs processados por minuto
  • Tempo de execução: média e máximo de tempo para completar jobs
  • Status dos workers: visualização de workers ativos, ociosos e ocupados

Para filtrar jobs específicos, utilize a barra de busca por nome de classe, tags ou status:

// Exemplo de job com tags para filtro no dashboard
class ProcessPayment implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    public function tags()
    {
        return ['payment', 'user:' . $this->user->id];
    }
}

5. Gerenciamento de Jobs e Falhas

O Horizon facilita a visualização e re-tentativa de jobs falhos diretamente pelo dashboard. Para configurar políticas de retry, utilize as propriedades no job:

class SendNotification implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    public $tries = 5;
    public $timeout = 120;
    public $backoff = [30, 60, 120, 240];
    public $maxExceptions = 3;
}

Para limpeza automática de jobs antigos, configure o HorizonServiceProvider:

protected function gate()
{
    Horizon::auth(function ($request) {
        return $request->user()->isAdmin();
    });
}

protected function boot()
{
    parent::boot();

    Horizon::pruneOldJobs(24); // Remove jobs com mais de 24 horas
    Horizon::pruneFailedJobs(48); // Remove jobs falhos com mais de 48 horas
}

A manutenção do Redis é essencial para performance. O Horizon já inclui comandos para limpeza:

php artisan horizon:clear
php artisan horizon:clear --queue=high

6. Notificações e Alertas

O Horizon permite configurar notificações para eventos críticos, como falhas consecutivas ou filas paradas. No HorizonServiceProvider:

use Laravel\Horizon\Horizon;
use Illuminate\Support\Facades\Notification;
use App\Notifications\HorizonAlert;

protected function boot()
{
    parent::boot();

    Horizon::routeSlackNotificationsTo('#horizon-alerts', env('SLACK_WEBHOOK_URL'));
    Horizon::routeSmsNotificationsTo('+5511999999999');
    Horizon::routeMailNotificationsTo('admin@example.com');
}

Para notificações customizadas, implemente listeners para eventos do Horizon:

Event::listen(\Laravel\Horizon\Events\LongWaitDetected::class, function ($event) {
    Notification::route('mail', 'devops@example.com')
        ->notify(new HorizonAlert($event));
});

Métricas críticas como latência acima de 5 segundos ou taxa de falhas superior a 10% podem disparar alertas automáticos.

7. Boas Práticas e Otimização

Durante deploys, siga este fluxo para evitar perda de jobs:

// 1. Pausar o Horizon
php artisan horizon:pause

// 2. Realizar o deploy (atualizar código, migrações, etc.)

// 3. Limpar cache de configurações
php artisan optimize:clear

// 4. Reiniciar o Horizon para recarregar configurações
php artisan horizon:terminate

// 5. Continuar o processamento
php artisan horizon:continue

Para otimização de performance, utilize tags para agrupar jobs relacionados:

public function tags()
{
    return ['batch:'.$this->batchId, 'type:email'];
}

Monitore o uso de memória do Redis com comandos como redis-cli info memory. Configure limites no config/horizon.php:

'limits' => [
    'memory' => 128, // MB
    'queue' => 10000, // Jobs máximos por fila
],

8. Conclusão e Próximos Passos

O Laravel Horizon transforma o gerenciamento de filas em uma experiência visual e automatizada. Com seu dashboard em tempo real, balanceamento inteligente e sistema de alertas, desenvolvedores podem focar na lógica de negócio enquanto o Horizon cuida da execução e monitoramento.

Para aprofundar, explore a integração com o Laravel Telescope para debugging avançado e com o Laravel Scout para busca em jobs. Considere também implementar filas com prioridades dinâmicas baseadas em carga do sistema.

Referências