Vai al contenuto
Blog

Engineering

Costruire funzionalità in tempo reale

Cursori live, chat, notifiche e dashboard: le scelte di trasporto e i pattern architetturali per funzionalità in tempo reale che restano affidabili sotto carico.

Di Pykero Agency · Engineering team8 lug 20266 min di lettura
Flussi di dati in tempo reale che pulsano tra client connessi su uno sfondo blu navy scuro

Il termine "tempo reale" copre un territorio molto ampio: una chat, una dashboard live, gli indicatori di presenza e i cursori collaborativi hanno esigenze molto diverse tra loro. Scegliere il trasporto o l'architettura sbagliati porta a funzionalità che funzionano in una demo e si sgretolano sotto carico reale. La buona notizia: la maggior parte delle esigenze real-time si mappa in modo preciso su pochi pattern ben consolidati. Ecco come scegliere.

Abbinare il trasporto alla necessità

La prima domanda da porsi è: i dati fluiscono in una direzione sola (dal server al client) o in entrambe?

  • Server-Sent Events (SSE): un flusso unidirezionale semplice dal server al client su HTTP standard. Ideale per notifiche, feed live, stream di attività e dashboard. Si riconnette automaticamente, funziona attraverso la maggior parte dei proxy ed è molto più semplice dei WebSocket. Spesso sottovalutato, eppure spesso la scelta giusta.
  • WebSocket: una connessione persistente full-duplex per comunicazioni bidirezionali a bassa latenza. La scelta corretta per chat, multiplayer, editing collaborativo e cursori live, ovunque il client invii dati con frequenza.
  • Polling / long-polling: interrogare il server ripetutamente. Grezzo, ma a volte la scelta pragmatica per aggiornamenti poco frequenti o ambienti vincolati. Non dovrebbe essere la scelta predefinita.

La regola pratica: se i client si limitano a ricevere, si utilizzi SSE; se i client inviano anche con continuità, si utilizzi WebSocket.

Non costruire tutto da zero, se non è necessario

Le connessioni persistenti sono facili da avviare e difficili da gestire in produzione. Prima di scrivere il proprio server WebSocket, è opportuno valutare i layer gestiti che risolvono le parti complesse (scaling, presenza, fan-out, riconnessione):

  • Supabase Realtime, se si è già su Postgres: trasmette le modifiche al database e la presenza via WebSocket con pochissimo codice server
  • I servizi pub/sub gestiti (Pusher, Ably e simili) si occupano dello scaling delle connessioni e delle garanzie di consegna
  • Il framework in uso potrebbe già offrire un'opzione batteries-included che vale la pena adottare

Costruire una soluzione proprietaria è giustificato in presenza di requisiti molto specifici o di economie di scala particolari, non come scelta predefinita.

L'architettura che scala

La parte difficile del real-time non è gestire una singola connessione, ma diecimila. Un singolo server può gestire un numero limitato di connessioni, e non appena si opera su più server, un client connesso al server A deve ricevere i messaggi pubblicati sul server B.

La soluzione standard è un backbone pub/sub (spesso Redis) posizionato a monte dei server di connessione:

  1. I server di connessione mantengono le connessioni WebSocket/SSE dei client
  2. Quando si verifica un evento, questo viene pubblicato su un canale nel layer pub/sub
  3. Ogni server di connessione si sottoscrive e invia il messaggio ai propri client rilevanti

Questo approccio disaccoppia "chi è connesso e dove" da "cosa deve essere trasmesso", permettendo di scalare orizzontalmente i server di connessione. I servizi real-time gestiti implementano già questo pattern, esonerando il team dall'onere di farlo.

Gestire le complessità reali

Le funzionalità in tempo reale si dimostrano valide o falliscono nella gestione dei casi di errore:

  • Riconnessione. Le connessioni si interrompono continuamente (reti mobili, sospensione del dispositivo, proxy). I client devono riconnettersi automaticamente con backoff.
  • Messaggi persi. Dopo una riconnessione, il client potrebbe aver perso degli aggiornamenti. È necessario supportare il recupero: reinviare i messaggi a partire da un cursore o timestamp, oppure recuperare lo stato completo alla riconnessione.
  • Presenza. Il rilevamento di "chi è online" richiede heartbeat e timeout per identificare le disconnessioni silenziose.
  • Ordinamento e conflitti. Per la collaborazione, occorre definire come risolvere le modifiche simultanee (last-write-wins, oppure CRDT/OT per il testo collaborativo reale).
  • Autenticazione. Si autentichi la connessione all'handshake e si autorizzi ciascuna sottoscrizione: non ci si fidi delle affermazioni del client sui canali a cui vuole accedere.

Il percorso pragmatico

Si utilizzi il trasporto più semplice che soddisfa la necessità (SSE molto più spesso di quanto i team assumano), ci si appoggi a un layer real-time gestito salvo ragioni concrete per non farlo, e si progetti fin dal primo giorno per la riconnessione e i messaggi persi. La maggior parte delle storie dell'orrore sul "real-time è difficile" nasce dall'aver saltato proprio quest'ultima parte.

Se si stanno aggiungendo funzionalità in tempo reale e si desidera un'architettura che resti affidabile oltre la fase demo, parliamone.

Engineeringreal-timewebsocketsarchitecture

Come può aiutare Pykero

Servizi collegati a questo articolo.

State costruendo qualcosa di simile?

Pykero Agency progetta e rilascia prodotti web, mobile, SaaS e AI pronti per la produzione.

Parliamone

Discussion

Be the first to comment.

Letture correlate