Utilizzo di WebSocket

Questa pagina fornisce indicazioni e best practice per l'esecuzione di WebSocket o altri servizi di streaming su Cloud Run e per la scrittura di client per questi servizi.

Le applicazioni WebSocket sono supportate su Cloud Run senza alcuna configurazione aggiuntiva. Tuttavia, gli stream WebSocket sono richieste HTTP ancora soggette al timeout della richiesta configurato per il servizio Cloud Run, quindi devi assicurarti che questa impostazione funzioni bene per il tuo utilizzo di WebSocket, ad esempio l'implementazione dei ricollegamenti nei tuoi client.

Anche se utilizzi l'affinità sessione Cloud Run, che offre l'affinità di massimo sforzo, le richieste WebSockets potrebbe comunque finire in istanze diverse, a causa della tecnologia il bilanciamento del carico. Per risolvere questo problema, sincronizzare i dati tra le istanze.

Tieni presente che WebSocket su Cloud Run sono supportati anche se utilizzi Cloud Load Balancing.

Deployment di un servizio WebSocket di esempio

Usa Cloud Shell per eseguire rapidamente il deployment di un servizio di lavagna di esempio che utilizza WebSocket con Cloud Run: Esegui il deployment di un esempio

In alternativa, se vuoi eseguire manualmente il deployment del servizio di lavagna di esempio:

  1. Clona in locale il repository Socket.IO utilizzando lo strumento a riga di comando git:

    git clone https://github.com/socketio/socket.io.git
    
  2. Vai alla directory di esempio:

    cd socket.io/examples/whiteboard/
    
  3. Esegui il deployment di un nuovo servizio Cloud Run compilandolo dal codice sorgente utilizzando Google Cloud CLI:

    gcloud run deploy whiteboard --allow-unauthenticated --source=.
    
  4. Una volta eseguito il deployment del servizio, apri due schede separate del browser e naviga all'URL del servizio. Tutto ciò che disegni in una scheda deve essere propagato all'altra scheda (e viceversa) poiché i client sono connessi alla stessa istanza tramite WebSocket.

Tutorial completo sulla chat di WebSockets

Se vuoi una procedura dettagliata completa del codice, sono disponibili altri esempi di codice in l'argomento Creazione di un servizio WebSocket Chat per Cloud Run.

Best practice

La parte più difficile della creazione di servizi WebSocket su Cloud Run è la sincronizzazione dei dati tra più istanze Cloud Run. Ciò è difficile a causa della scalabilità automatica natura delle istanze e a causa dei limiti contemporaneità e timeout delle richieste.

Gestione dei timeout delle richieste e delle riconnessioni del client

Le richieste WebSocket vengono trattate come richieste HTTP di lunga durata in Cloud Run. Sono soggetti a timeout delle richieste (attualmente fino a 60 minuti e il valore predefinito è 5 minuti) anche se il server delle applicazioni non applica alcun timeout.

Di conseguenza, se il client mantiene la connessione aperta più a lungo del tempo di attesa obbligatorio configurato per il servizio Cloud Run, verrà disconnesso al termine del tempo di attesa della richiesta.

Pertanto, i client WebSocket che si connettono a Cloud Run devono gestire la riconnessione al server se la richiesta scade o se il server si disconnette. È possibile raggiungere questo obiettivo nei client basati su browser utilizzando librerie come reconnecting-websocket o tramite gestione di "disconnect" eventi se utilizzi SocketIO.

Fatturazione relativa all'utilizzo di WebSocket

Un'istanza Cloud Run che ha qualsiasi connessione WebSocket aperta considerata attiva, pertanto la CPU viene allocata e fatturata.

Massimizzazione della concorrenza

I servizi WebSockets sono in genere progettati per gestire molte connessioni contemporaneamente. Poiché Cloud Run supporta le connessioni simultanee (fino a 1000 per contenitore), Google consiglia di aumentare l'impostazione di concorrenza massima per il contenitore a un valore superiore a quello predefinito se il servizio è in grado di gestire il carico con determinate risorse.

Informazioni sulle sessioni fisse (affinità sessione)

Poiché le connessioni WebSocket sono stateful, il client rimarrà connesso lo stesso container su Cloud Run per tutta la durata connessione. Ciò offre naturalmente una persistenza della sessione nel contesto di una singola connessione WebSocket.

Per più connessioni WebSocket successive, puoi configurare il servizio Cloud Run in modo da utilizzare l'affinità di sessione, ma questo fornisce un'affinità best effort, pertanto le richieste WebSocket potrebbero comunque finire in istanze diverse. Clienti che si connette al tuo servizio Cloud Run potrebbe essere gestito da diverse istanze che non coordinano né condividono dati.

Per ovviare a questo problema, devi utilizzare uno spazio di archiviazione dati esterno per sincronizzare lo stato tra le istanze Cloud Run, come spiegato nella prossima sezione.

Sincronizzazione dei dati tra le istanze

Devi sincronizzare i dati per assicurarti che i client si connettano a un Il servizio Cloud Run riceve gli stessi dati dalla connessione WebSockets.

Ad esempio, supponiamo che tu stia creando un servizio di chatroom utilizzando WebSocket e impostato l'impostazione Contemporaneità massima su 1000. Se più di 1000 utenti si connettono a questo servizio contemporaneamente, verranno gestiti da istanze diverse e, di conseguenza, non potranno vedere gli stessi messaggi nella chatroom.

Per sincronizzare i dati tra le tue istanze Cloud Run, ad esempio che ricevono i messaggi pubblicati in una chat room da tutte le istanze, è necessaria di archiviazione dati esterno, come un database o una coda di messaggi.

Se utilizzi un database esterno come Cloud SQL, puoi inviare messaggi al database ed eseguire periodicamente poll dal database. Tuttavia, tieni presente che le istanze Cloud Run non hanno CPU quando il contenitore non gestisce richieste. Se il tuo servizio gestisce principalmente richieste WebSockets, la CPU verrà allocata al contenitore purché sia collegato almeno un client.

Le code di messaggi funzionano meglio per sincronizzare i dati tra i contenitori Cloud Run in tempo reale, perché le code di messaggi esterne non possono indirizzare ogni istanza per "inviare" i dati. I servizi devono "estrarre" i nuovi messaggi dalla coda dei messaggi stabilendo una connessione alla coda.

Google consiglia di utilizzare sistemi di coda dei messaggi esterni come Redis Pub/Sub (Memorystore) oppure Aggiornamenti di Firestore in tempo reale che può fornire aggiornamenti a tutte le istanze tramite le connessioni avviate dal container in esecuzione in un'istanza Compute Engine.

Utilizzo di Redis Pub/Sub

Architettura del servizio di chatroom WebSocket

Puoi utilizzare il meccanismo Redis Pub/Sub creando un'istanza Redis da Memorystore. Se utilizzando la libreria Socket.IO per WebSocket, puoi utilizzare i suoi redis dell'adattatore.

In questa architettura basata su Redis, ogni istanza Cloud Run stabilisce una connessione a lungo termine con il canale Redis che contiene i messaggi ricevuti (utilizzando il comando SUBSCRIBE). Una volta creato il container, istanze ricevono un nuovo messaggio sul canale, possono inviarlo tramite WebSocket in tempo reale.

Analogamente, quando un client invia un messaggio utilizzando WebSocket, che riceve il messaggio, lo pubblica su Redis canale (utilizzando il comando PUBLISH) e altre istanze iscritte a questo canale riceveranno per creare un nuovo messaggio email.

Se vuoi una procedura dettagliata completa del codice, sono disponibili altri esempi di codice in l'argomento Creazione di un servizio WebSocket Chat per Cloud Run.