Blog

Websocket in Laravel senza gestire un server websocket

· Andrij Tkachenko · 5 min di lettura

La finestra di un editor di codice collegata da una linea a un cloud, che invia aggiornamenti in tempo reale a quattro finestre del browser

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. Con ShouldBroadcast questo 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:

.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:

PHP
// 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:

JavaScript
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() e leaving() per sapere chi è in una stanza, whisper() per gli indicatori di scrittura e notification() 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.