Websocket in Laravel senza gestire un server websocket

Laravel fa sembrare facili gli aggiornamenti in tempo reale. Un evento implementa ShouldBroadcast, routes/channels.php stabilisce chi può ascoltarlo, e Laravel Echo nel browser lo riceve. Un ordine passa a spedito, e il cliente lo vede senza ricaricare la pagina.
Quello che la documentazione dice solo di sfuggita è che qualcosa deve tenere la connessione con ogni browser aperto. Laravel di per sé risponde alle richieste e si ferma, quindi il broadcasting ha sempre bisogno di un server websocket accanto alla tua app. Questo articolo spiega perché, cosa serve per gestirne uno in produzione e come tenere i tuoi eventi ed Echo esattamente come sono mentre un cloud in tempo reale tiene le connessioni al posto tuo.
Perché Laravel ha bisogno di un server websocket
Una richiesta Laravel è breve. PHP riceve la richiesta, Laravel si avvia, il tuo controller risponde e il processo è libero per la richiesta successiva. È questo che rende Laravel veloce e semplice da ospitare, ed è anche il motivo per cui una richiesta non può restare aperta per ore a inviare aggiornamenti a un browser.
Il broadcasting ha quindi due metà:
- La tua app invia. Quando chiami
broadcast( new OrderUpdated( $order ) ), Laravel passa l’evento a un broadcaster, che lo inoltra con una breve richiesta. ConShouldBroadcastquesto avviene in un job in coda, quindi lo esegue un queue worker. - Qualcos’altro consegna. Un server websocket tiene una connessione aperta con ogni browser, chiede alla tua app chi può entrare in ogni canale privato e passa ogni evento ai browser in ascolto.
La prima metà è Laravel di tutti i giorni. La seconda è un servizio separato, sempre in esecuzione, ed è lì che sta il lavoro.
Gestire un server websocket tutto tuo
Laravel ha un server websocket che puoi gestire da solo, e lo stesso vale per altri progetti. Avviarne uno sul tuo portatile richiede un minuto. Farlo funzionare per utenti reali richiede di più:
- Un processo sempre in esecuzione, tenuto in vita da un process manager, riavviato quando va in crash, con i suoi log e il suo monitoraggio. Gli hosting condivisi e le piattaforme serverless non possono proprio eseguirne uno.
- Una porta, un certificato e un proxy, perché i browser possano collegarsi via
wss://sul tuo dominio, con il proxy configurato per far passare i websocket e non interrompere le connessioni lunghe. - Spazio per molte connessioni. Ogni browser aperto è una connessione aperta, e il server e il sistema operativo devono avere limiti impostati per migliaia di connessioni contemporanee.
- Più di un server, man mano che cresci. Un solo server è un unico punto in cui ogni connessione può cadere. Due o più hanno bisogno di un canale condiviso, di solito Redis, perché un evento inviato a uno raggiunga i browser collegati agli altri.
- Deploy senza tempeste di riconnessioni. Riavviare il server websocket fa cadere ogni connessione, e ogni browser si riconnette nello stesso momento. Le pagine rimaste scollegate perdono anche ciò che è stato inviato nel frattempo, a meno che qualcosa non lo conservi per loro.
Niente di tutto questo è esotico, e molti team lo fanno bene. Ma è un secondo sistema da tenere in funzione accanto alla tua app, finché l’app ha funzioni in tempo reale.
Oppure lascia che sia un cloud in tempo reale a tenere le connessioni
L’altra strada è usare un servizio gestito come broadcaster. La tua app invia ogni evento con una breve richiesta HTTP, come fa già con un broadcaster, e il servizio tiene le connessioni, verifica le regole dei tuoi canali tramite la tua app e consegna. La tua app Laravel resta una normale app Laravel, su qualsiasi hosting, serverless incluso.
Ciò che conta è che il passaggio avvenga all’interno del broadcasting di Laravel stesso, così i tuoi eventi, i tuoi canali e il tuo codice Echo restano come sono.
Il broadcasting di Laravel su WordPlus Cloud
Con WordPlus Cloud, a cambiare è la connessione di broadcasting, indicata nel tuo .env:
BROADCAST_CONNECTION=wordplus
WORDPLUS_SITE=s1500000007
WORDPLUS_SECRET=…
WORDPLUS_LOCAL_KEY=…I tuoi canali restano in routes/channels.php, con un argomento facoltativo per ciò che ogni stanza conserva:
// The room of an order, orders.1042, for its customer, the last 20 updates kept.
Broadcast::channel( 'orders.{order}', fn ( User $user, Order $order ) => $user->id === $order->customer_id, [ 'history' => 20 ] );I tuoi eventi restano come sono, e broadcast( new OrderUpdated( $order ) ) li invia. Nel browser, Echo usa il nostro connettore al posto di quello abituale:
import Echo from 'laravel-echo';
import { WordplusConnector } from '@wordplus/realtime/echo';
window.Echo = new Echo( { broadcaster: WordplusConnector, ...window.wordplusRealtimeConfig } );
Echo.private( 'orders.1042' ).listen( '.updated', ( data ) => showStatus( data.status ) );La direttiva @wordplusRealtime nel tuo layout scrive quella configurazione insieme all’utente autenticato, così la pagina si collega senza fare prima nessuna richiesta. Da lì funziona tutto ciò che conosci di Echo:
- Canali privati e di presenza, con
here(),joining()eleaving()per sapere chi è in una stanza,whisper()per gli indicatori di scrittura enotification()per le notifiche di Laravel. - Livewire riceve gli eventi allo stesso modo, con
#[On( 'echo-private:orders.{order.id},.updated' )]. - React e Vue usano
useEcho()dai pacchetti Echo ufficiali di Laravel, come fanno gli starter kit. toOthers()esclude la scheda che ha inviato la richiesta.
E in più ciò che un server websocket da solo non ti dà:
- Nessun server websocket da gestire. I nostri server tengono le connessioni, se ne avviano altri man mano che la tua app cresce, e una pagina passa da uno all’altro senza cadere quando uno si riavvia.
- Nulla si perde alla riconnessione. Una stanza conserva i suoi ultimi eventi, così una pagina che torna riceve ciò che si è persa, in ordine.
- Sigillato lungo il tragitto. Ciò che la tua app invia viaggia cifrato con chiavi che hanno solo la tua app e i tuoi utenti.
- Chiamate e live streaming sulla stessa connessione. Chiamate tra due persone, chiamate di gruppo e live streaming, con una schermata di chiamata e un player pronti da usare, o i tuoi.
La guida per Laravel contiene tutta la configurazione, e la demo dal vivo è un piccolo negozio costruito su di essa, dove un ordine passa a spedito in un’altra finestra mentre fai clic.
WordPlus Cloud for Apps ha un prezzo in base alle connessioni simultanee, a partire da 1.000, con fatturazione mensile o annuale. Scopri cosa fa per le app, o i prezzi per le app. Domande sulla tua integrazione? Scrivici.