Laravel Reverb
Introdução
Laravel Reverb traz comunicação WebSocket em tempo real extremamente rápida e escalável diretamente para seu aplicativo Laravel e fornece integração perfeita com o conjunto existente de ferramentas de transmissão de eventos do Laravel.
Instalação
Você pode instalar o Reverb usando o comando Artisan install:broadcasting
:
php artisan install:broadcasting
Configuração
Nos bastidores, o comando Artisan install:broadcasting
executará o comando reverb:install
, que instalará o Reverb com um conjunto sensato de opções de configuração padrão. Se você quiser fazer alguma alteração na configuração, pode fazê-lo atualizando as variáveis de ambiente do Reverb ou atualizando o arquivo de configuração config/reverb.php
.
Credenciais do aplicativo
Para estabelecer uma conexão com o Reverb, um conjunto de credenciais de "aplicativo" do Reverb deve ser trocado entre o cliente e o servidor. Essas credenciais são configuradas no servidor e são usadas para verificar a solicitação do cliente. Você pode definir essas credenciais usando as seguintes variáveis de ambiente:
REVERB_APP_ID=my-app-id
REVERB_APP_KEY=my-app-key
REVERB_APP_SECRET=my-app-secret
Origens permitidas
Você também pode definir as origens das quais as solicitações do cliente podem se originar atualizando o valor da configuração allowed_origins
na seção apps
do arquivo de configuração config/reverb.php
. Quaisquer solicitações de uma origem não listada em suas origens permitidas serão rejeitadas. Você pode permitir todas as origens usando *
:
'apps' => [
[
'id' => 'my-app-id',
'allowed_origins' => ['laravel.com'],
// ...
]
]
Aplicativos adicionais
Normalmente, o Reverb fornece um servidor WebSocket para o aplicativo no qual está instalado. No entanto, é possível atender mais de um aplicativo usando uma única instalação do Reverb.
Por exemplo, você pode desejar manter um único aplicativo Laravel que, via Reverb, fornece conectividade WebSocket para vários aplicativos. Isso pode ser obtido definindo vários apps
no arquivo de configuração config/reverb.php
do seu aplicativo:
'apps' => [
[
'app_id' => 'my-app-one',
// ...
],
[
'app_id' => 'my-app-two',
// ...
],
],
SSL
Na maioria dos casos, as conexões WebSocket seguras são manipuladas pelo servidor web upstream (Nginx, etc.) antes que a solicitação seja enviada por proxy para seu servidor Reverb.
No entanto, às vezes pode ser útil, como durante o desenvolvimento local, para o servidor Reverb manipular conexões seguras diretamente. Se você estiver usando o recurso de site seguro do Laravel Herd ou estiver usando o Laravel Valet e tiver executado o comando secure em seu aplicativo, você pode usar o certificado Herd / Valet gerado para seu site para proteger suas conexões Reverb. Para fazer isso, defina a variável de ambiente REVERB_HOST
para o nome do host do seu site ou passe explicitamente a opção hostname ao iniciar o servidor Reverb:
php artisan reverb:start --host="0.0.0.0" --port=8080 --hostname="laravel.test"
Como os domínios Herd e Valet resolvem para localhost
, executar o comando acima resultará no seu servidor Reverb sendo acessível por meio do protocolo WebSocket seguro (wss
) em wss://laravel.test:8080
.
Você também pode escolher manualmente um certificado definindo as opções tls
no arquivo de configuração config/reverb.php
do seu aplicativo. Dentro do array de opções tls
, você pode fornecer qualquer uma das opções suportadas pelas opções de contexto SSL do PHP:
'options' => [
'tls' => [
'local_cert' => '/path/to/cert.pem'
],
],
Executando o servidor
O servidor Reverb pode ser iniciado usando o comando Artisan reverb:start
:
php artisan reverb:start
Por padrão, o servidor Reverb será iniciado em 0.0.0.0:8080
, tornando-o acessível de todas as interfaces de rede.
Se você precisar especificar um host ou porta personalizado, você pode fazer isso através das opções --host
e --port
ao iniciar o servidor:
php artisan reverb:start --host=127.0.0.1 --port=9000
Alternativamente, você pode definir as variáveis de ambiente REVERB_SERVER_HOST
e REVERB_SERVER_PORT
no arquivo de configuração .env
do seu aplicativo.
As variáveis de ambiente REVERB_SERVER_HOST
e REVERB_SERVER_PORT
não devem ser confundidas com REVERB_HOST
e REVERB_PORT
. As primeiras especificam o host e a porta nos quais executar o próprio servidor Reverb, enquanto o último par instrui o Laravel para onde enviar mensagens de transmissão. Por exemplo, em um ambiente de produção, você pode rotear solicitações do seu nome de host público do Reverb na porta 443
para um servidor Reverb operando em 0.0.0.0:8080
. Neste cenário, suas variáveis de ambiente seriam definidas da seguinte forma:
REVERB_SERVER_HOST=0.0.0.0
REVERB_SERVER_PORT=8080
REVERB_HOST=ws.laravel.com
REVERB_PORT=443
Debugging
Para melhorar o desempenho, o Reverb não emite nenhuma informação de depuração por padrão. Se você quiser ver o fluxo de dados passando pelo seu servidor Reverb, você pode fornecer a opção --debug
para o comando reverb:start
:
php artisan reverb:start --debug
Reiniciando
Como o Reverb é um processo de longa duração, as alterações no seu código não serão refletidas sem reiniciar o servidor por meio do comando Artisan reverb:restart
.
O comando reverb:restart
garante que todas as conexões sejam encerradas normalmente antes de parar o servidor. Se você estiver executando o Reverb com um gerenciador de processos como o Supervisor, o servidor será reiniciado automaticamente pelo gerenciador de processos após todas as conexões terem sido encerradas:
php artisan reverb:restart
Monitoramento
O Reverb pode ser monitorado por meio de uma integração com o Laravel Pulse. Ao habilitar a integração do Reverb com o Pulse, você pode rastrear o número de conexões e mensagens sendo manipuladas pelo seu servidor.
Para habilitar a integração, você deve primeiro garantir que tenha instalado o Pulse. Em seguida, adicione qualquer um dos gravadores do Reverb ao arquivo de configuração config/pulse.php
do seu aplicativo:
use Laravel\Reverb\Pulse\Recorders\ReverbConnections;
use Laravel\Reverb\Pulse\Recorders\ReverbMessages;
'recorders' => [
ReverbConnections::class => [
'sample_rate' => 1,
],
ReverbMessages::class => [
'sample_rate' => 1,
],
...
],
Em seguida, adicione os cartões Pulse para cada gravador ao seu painel do Pulse:
<x-pulse>
<livewire:reverb.connections cols="full" />
<livewire:reverb.messages cols="full" />
...
</x-pulse>
Executando o Reverb em produção
Devido à natureza de longa execução dos servidores WebSocket, pode ser necessário fazer algumas otimizações no seu servidor e ambiente de hospedagem para garantir que seu servidor Reverb possa efetivamente lidar com o número ideal de conexões para os recursos disponíveis em seu servidor.
NOTA
Se seu site for gerenciado pelo Laravel Forge, você pode otimizar automaticamente seu servidor para o Reverb diretamente do painel "Aplicativo". Ao habilitar a integração do Reverb, o Forge garantirá que seu servidor esteja pronto para produção, incluindo a instalação de quaisquer extensões necessárias e o aumento do número permitido de conexões.
Arquivos abertos
Cada conexão WebSocket é mantida na memória até que o cliente ou o servidor se desconecte. Em ambientes Unix e semelhantes ao Unix, cada conexão é representada por um arquivo. No entanto, geralmente há limites no número de arquivos abertos permitidos no nível do sistema operacional e do aplicativo.
Sistema operacional
Em um sistema operacional baseado em Unix, você pode determinar o número permitido de arquivos abertos usando o comando ulimit
:
ulimit -n
Este comando exibirá os limites de arquivos abertos permitidos para diferentes usuários. Você pode atualizar esses valores editando o arquivo /etc/security/limits.conf
. Por exemplo, atualizar o número máximo de arquivos abertos para 10.000 para o usuário forge
ficaria assim:
# /etc/security/limits.conf
forge soft nofile 10000
forge hard nofile 10000
Loop de eventos
Por baixo dos panos, o Reverb usa um loop de eventos ReactPHP para gerenciar conexões WebSocket no servidor. Por padrão, esse loop de eventos é alimentado por stream_select
, que não requer nenhuma extensão adicional. No entanto, stream_select
é normalmente limitado a 1.024 arquivos abertos. Dessa forma, se você planeja lidar com mais de 1.000 conexões simultâneas, precisará usar um loop de eventos alternativo não vinculado às mesmas restrições.
O Reverb alternará automaticamente para um loop alimentado por ext-uv
quando disponível. Esta extensão PHP está disponível para instalação via PECL:
pecl install uv
Servidor Web
Na maioria dos casos, o Reverb é executado em uma porta não voltada para a web no seu servidor. Então, para rotear o tráfego para o Reverb, você deve configurar um proxy reverso. Supondo que o Reverb esteja sendo executado no host 0.0.0.0
e na porta 8080
e seu servidor utilize o servidor web Nginx, um proxy reverso pode ser definido para seu servidor Reverb usando a seguinte configuração de site Nginx:
server {
...
location / {
proxy_http_version 1.1;
proxy_set_header Host $http_host;
proxy_set_header Scheme $scheme;
proxy_set_header SERVER_PORT $server_port;
proxy_set_header REMOTE_ADDR $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_pass http://0.0.0.0:8080;
}
...
}
Normalmente, os servidores web são configurados para limitar o número de conexões permitidas para evitar sobrecarga do servidor. Para aumentar o número de conexões permitidas em um servidor web Nginx para 10.000, os valores worker_rlimit_nofile
e worker_connections
do arquivo nginx.conf
devem ser atualizados:
user forge;
worker_processes auto;
pid /run/nginx.pid;
include /etc/nginx/modules-enabled/*.conf;
worker_rlimit_nofile 10000;
events {
worker_connections 10000;
multi_accept on;
}
A configuração acima permitirá que até 10.000 workers Nginx por processo sejam gerados. Além disso, essa configuração define o limite de arquivos abertos do Nginx para 10.000.
Portas
Os sistemas operacionais baseados em Unix geralmente limitam o número de portas que podem ser abertas no servidor. Você pode ver o intervalo permitido atual por meio do seguinte comando:
cat /proc/sys/net/ipv4/ip_local_port_range
# 32768 60999
A saída acima mostra que o servidor pode manipular no máximo 28.231 (60.999 - 32.768) conexões, pois cada conexão requer uma porta livre. Embora recomendemos escalonamento horizontal para aumentar o número de conexões permitidas, você pode aumentar o número de portas abertas disponíveis atualizando o intervalo de portas permitidas no arquivo de configuração /etc/sysctl.conf
do seu servidor.
Gerenciamento de Processos
Na maioria dos casos, você deve usar um gerenciador de processos como o Supervisor para garantir que o servidor Reverb esteja em execução contínua. Se estiver usando o Supervisor para executar o Reverb, você deve atualizar a configuração minfds
do arquivo supervisor.conf
do seu servidor para garantir que o Supervisor consiga abrir os arquivos necessários para manipular conexões com seu servidor Reverb:
[supervisord]
...
minfds=10000
Escalonamento
Se você precisar manipular mais conexões do que um único servidor permitirá, você pode escalonar seu servidor Reverb horizontalmente. Utilizando os recursos de publicação/assinatura do Redis, o Reverb consegue gerenciar conexões em vários servidores. Quando uma mensagem é recebida por um dos servidores Reverb do seu aplicativo, o servidor usará o Redis para publicar a mensagem recebida em todos os outros servidores.
Para habilitar o dimensionamento horizontal, você deve definir a variável de ambiente REVERB_SCALING_ENABLED
como true
no arquivo de configuração .env
do seu aplicativo:
REVERB_SCALING_ENABLED=true
Em seguida, você deve ter um servidor Redis central dedicado ao qual todos os servidores Reverb se comunicarão. O Reverb usará a conexão Redis padrão configurada para seu aplicativo para publicar mensagens em todos os seus servidores Reverb.
Depois de habilitar a opção de dimensionamento do Reverb e configurar um servidor Redis, você pode simplesmente invocar o comando reverb:start
em vários servidores que podem se comunicar com seu servidor Redis. Esses servidores Reverb devem ser colocados atrás de um balanceador de carga que distribui as solicitações recebidas uniformemente entre os servidores.