Tiempo real con Reverb
Enciende el servidor WebSocket opcional para que el pago de complementos y la campana de notificaciones se actualicen solos, en local y en un servidor de Ploi.
El kit viene con el tiempo real apagado. Apagado, todo funciona como siempre: las pantallas de complementos preguntan al servidor cada pocos segundos mientras un pago está esperando, y la campana de notificaciones muestra lo que había al cargar la página. El chat de soporte en vivo es la excepción: necesita el tiempo real y no se ofrece sin él. Enciéndelo y esto reacciona en menos de un segundo, sin sondeo:
| Pantalla | Con el tiempo real apagado | Con el tiempo real encendido |
|---|---|---|
| Catálogo de complementos y detalle de un complemento, después de pagar | Consulta cada 3 segundos (catálogo) o cada 5 segundos (detalle) hasta que Stripe confirma el pago | Sin sondeo. Cada webhook de Stripe sobre la cuenta avisa a sus pantallas de cobro abiertas que revisen, y la confirmación aparece en cuanto llega el webhook |
| Campana de notificaciones de la barra superior | El contador y la lista se cargan con la página | Una notificación nueva actualiza el contador y la lista en cada pestaña abierta de la persona a la que se envió, y solo de esa persona |
| Chat de soporte en vivo, para el cliente y en la página de chats del equipo | No disponible: un cliente que lo abre lee "Tenemos un problema técnico en este momento" y, cuando los tickets están encendidos, se le ofrece Enviar un ticket | Cada cambio de un chat le llega al cliente dueño y a todos los del equipo que pueden contestar chats. La guía «Chat de soporte en vivo», disponible cuando el chat en vivo está encendido, lo explica |
La decisión es de la aplicación, no de cada pantalla: el tiempo real está encendido cuando la conexión de broadcasting es reverb, y apagado con cualquier otro valor. Esa conexión es BROADCAST_CONNECTION cuando el entorno la escribe, y el valor por defecto del proyecto cuando no (ve Enciéndelo o apágalo). No hay respaldo: si Reverb está encendido y su servidor está caído, nada se rompe, solo que las pantallas dejan de actualizarse solas hasta que vuelva (un pago se confirma igual; la persona lo ve al recargar).
Reverb es un proceso propio que corre en el mismo servidor que la aplicación, así que comparte la memoria y el procesador de ese servidor. Es ligero, pero es una cosa más que mantener viva, y por eso el kit deja la elección a cada producto.
Qué interviene
- Lado del servidor.
laravel/reverbes el servidor WebSocket. La transmisión es inmediata (ShouldBroadcastNow), así que no necesita el worker de la cola. - Lado del navegador.
laravel-echoypusher-jsvan empaquetados enresources/js/bootstrap.js. El diseño solo le entrega al navegador los datos de conexión cuando la persona inició sesión y el tiempo real está encendido, así que un visitante sin sesión, o cualquier página con el tiempo real apagado, nunca abre una conexión. - Canales. Tres canales privados, todos autorizados en
POST /broadcasting/auth:App.Models.User.{id}(solo ese usuario, declarado enroutes/channels.php) llevanotification.receivedy, para el cliente de un chat en vivo,support-chat.updated;support-chats(quien puede contestar tickets, mientras el chat en vivo está encendido, declarado enroutes/channels.php) le llevasupport-chat.updatedal equipo;billing-account.{id}(solo quien puede administrar esa cuenta de cobro, declarado por Billing Core) llevabilling-account.updated.
Pruébalo en local
-
Asegúrate de tener las dependencias instaladas:
composer installynpm install(laravel/reverb,laravel-echoypusher-jsvienen con el kit). -
Agrega a tu
.envlocal. Los tres valores de la app son cadenas aleatorias que tú eliges;php -r "echo bin2hex(random_bytes(16));"genera una.BROADCAST_CONNECTION=reverb REVERB_APP_ID=local REVERB_APP_KEY=a-random-string REVERB_APP_SECRET=another-random-string REVERB_HOST=weblabor-base.test REVERB_PORT=8080 REVERB_SCHEME=httpsUsa el nombre de tu propio sitio en
REVERB_HOST. No corrasphp artisan reverb:installniphp artisan install:broadcasting: el kit ya está conectado, y ambos comandos reescriben archivos que son suyos. -
Arranca el servidor nombrando el sitio seguro de Herd o Valet, para que Reverb sirva TLS con su certificado (una página
httpsno puede abrir una conexiónws://simple):php artisan reverb:start --hostname=weblabor-base.test --debug -
php artisan config:clear, luegonpm run dev(onpm run build) y recarga la página. Con--debugla terminal imprime cada conexión y cada mensaje. -
Revisa los dos casos. Compra un complemento con una tarjeta de prueba de Stripe y la confirmación aparece en cuanto llega el webhook (reenvía los webhooks con
stripe listenen local), sin peticionescheckSubscriptionStatusnicheckPendingrepitiéndose en la pestaña de red. Luego haz que le llegue una notificación a alguien, por ejemplo respondiendo su ticket desde otra cuenta, y su campana cambia sin recargar mientras la de otra persona con sesión abierta no.
Enciéndelo o apágalo
Encender: pon BROADCAST_CONNECTION=reverb con los valores REVERB_*, arranca el proceso de Reverb y corre php artisan config:clear (o php artisan optimize si guardas la configuración en caché). Apagar: pon BROADCAST_CONNECTION=null (o quítala, null es el valor por defecto), corre el mismo comando y detén el proceso. No hay que reconstruir nada: el navegador lee los datos de la página, no del paquete de recursos.
BROADCAST_CONNECTION siempre manda cuando el entorno la escribe. Sin ella, la conexión es el valor por defecto del proyecto, una línea al principio de config/broadcasting.php:
$projectDefault = 'null';
El kit la trae en null, así que el tiempo real sigue apagado hasta que un servidor lo enciende. Un producto que lo quiere encendido dondequiera que Reverb esté configurado, por ejemplo para ofrecer el chat de soporte en vivo por defecto, escribe ahí 'reverb'. Entonces cada entorno decide según sus propias credenciales:
| Entorno | Resultado |
|---|---|
Sin BROADCAST_CONNECTION, con REVERB_APP_ID, REVERB_APP_KEY y REVERB_APP_SECRET las tres con valor |
Tiempo real encendido, sin escribir nada en ese .env |
Sin BROADCAST_CONNECTION, con cualquiera de las tres ausente o vacía |
Tiempo real apagado, como si el valor por defecto fuera null: la aplicación, artisan y las pruebas arrancan, y las pantallas de complementos siguen consultando |
BROADCAST_CONNECTION=null, o cualquier otra conexión |
Esa conexión, haya credenciales o no |
BROADCAST_CONNECTION=reverb con las tres credenciales |
Tiempo real encendido |
BROADCAST_CONNECTION=reverb con cualquiera de las tres ausente |
La aplicación no arranca, y el error nombra las variables de Reverb que están vacías |
El último caso no cae a null en silencio: escribir reverb y olvidar las credenciales es un error de ese entorno, y el mensaje dice qué valores faltan en lugar de fallar en lo profundo del cliente de Pusher. Las pruebas corren siempre con BROADCAST_CONNECTION=null, diga lo que diga tu .env local; una prueba que necesita el tiempo real lo enciende ella misma.
Despliégalo en Ploi
Ploi mantiene vivos los procesos con Supervisor y sirve el sitio con Nginx. Puede correr Reverb por ti, pero no escribe el bloque de Nginx que reenvía el tráfico del WebSocket: esa parte es tuya.
-
Supervisor. Reverb corre como un daemon de Ploi, y los daemons corren bajo Supervisor, así que Supervisor tiene que estar instalado y en marcha en el servidor. Un servidor que ya corre el worker de la cola como daemon de Ploi lo tiene; en uno nuevo, revísalo entre los servicios del servidor antes de agregar el daemon.
-
El proceso de Reverb. En los Daemons del servidor, agrega uno:
Campo Valor Command php /home/ploi/your-domain.com/artisan reverb:start --host=127.0.0.1 --port=8080User ploiProcesses 1Escucha solo en el propio servidor, puerto 8080; Nginx es lo único que lo alcanza.
-
Nginx. En Manage del sitio, abre la configuración de Nginx y agrega, dentro del bloque
serverque escucha en 443, las dos rutas que usa Reverb:/apppara las conexiones WebSocket de los navegadores y/appspara que la aplicación publique eventos.location /app { 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://127.0.0.1:8080; } location /apps { 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://127.0.0.1:8080; }Guárdalo; Ploi prueba y recarga Nginx.
-
Entorno. En el entorno del sitio, con tus propios valores aleatorios:
BROADCAST_CONNECTION=reverb REVERB_APP_ID=your-app-id REVERB_APP_KEY=your-app-key REVERB_APP_SECRET=your-app-secret REVERB_HOST=your-domain.com REVERB_PORT=443 REVERB_SCHEME=httpsREVERB_HOST,REVERB_PORTyREVERB_SCHEMEson la dirección pública, la que responde Nginx, y la usan tanto los navegadores como la aplicación para publicar. El proceso sigue escuchando en 127.0.0.1:8080. -
Script de despliegue. Los comandos de siempre ya reconstruyen los recursos de la aplicación (
npm ciynpm run build), que es lo que empaqueta Echo; consérvalos. Agrega, después dephp artisan queue:restart:php artisan reverb:restartIgual que el worker de la cola, Reverb guarda en memoria el código con el que arrancó, y esto es lo que hace que Supervisor lo vuelva a arrancar con la versión nueva.
Los pasos de Ploi están documentados aquí pero el kit no los prueba. Después del primer despliegue, abre una página con sesión y revisa en la pestaña de red del navegador que la conexión a wss://your-domain.com/app/... se abre con estado 101.