2012-11-13 13 views
15

Sto pianificando di installare un gruppo di server applicazioni NodeJS con Socket.io su EC2 e vorrei utilizzare lo Elastic Load Balancer per distribuire il carico tra di loro. So che ELB non supporta Websockets, ma posso usare la configurazione descritta here in Scenario 2.Socket.io Websockets su un Amazon Balanced Load Balancer TCP configurato

Come descritto nel the blog post, però, ho notato che questa configurazione offre alcuna affinità di sessione o fonte di informazioni IP:

Non possiamo avere affinità di sessione, né le intestazioni X-avanti con questa configurazione perché ELB non è analizzando i messaggi HTTP, quindi è impossibile per abbinare i cookie per garantire Session Affinity né iniettare intestazioni speciali X-Forward .

Will Socket.io funziona ancora in queste circostanze? O c'è un altro modo per avere un set di app server Socket.io dietro un load balancer con SSL?

EDIT: Tim Caswell parla di fare questo già here. Ci sono post che spiegano come impostare questo? Ancora una volta non c'è appiccicosità alla sessione, ma le cose sembrano funzionare bene.

Per inciso, le sessioni adesive sono effettivamente necessarie con le web socket? Le informazioni viaggiano come nuove e separate richieste o c'è solo una richiesta + connessione in cui tutte le informazioni si muovono?

+0

Risposta rapida - no, socket.io non funzionerà se le richieste successive andranno su server diversi, è necessario trovare un modo per implementare sessioni "persistenti" nella configurazione. – Dmitry

+0

@Dmitry: sei sicuro? Penso che socket.io dovrebbe funzionare se si utilizza un negozio condiviso, ad es. il RedisStore? –

+0

@LinusGThiel non funzionerà senza sessione appiccicosa, ecco alcuni dettagli in più: https://groups.google.com/d/topic/socket_io/d9a8c49uymc/discussion – Dmitry

risposta

12

È ora possibile utilizzare il nuovo servizio di bilanciamento del carico recentemente lanciato da AWS.

basta sostituire l'ELB (ora chiamato bilanciamento del carico Classic) con l'ALB (load balancer Application) e abilitare le sessioni appiccicoso.

ALB supporta prese Web. Questo dovrebbe fare il trucco.

https://aws.amazon.com/blogs/aws/new-aws-application-load-balancer/

http://docs.aws.amazon.com/elasticloadbalancing/latest/application/introduction.html

+0

ci sono serie conseguenze di allontanarsi da ELB e usare ALB? Socket.io ha iniziato a lavorare nel mio caso, ma sono un po 'preoccupato per le altre possibili conseguenze nell'architettura ... C'è qualche svantaggio nell'usare ALB su ELB? – user3766930

+1

@ user3766930 Non ho riscontrato alcun problema dal passaggio ad ALB. Lo sto usando da sei mesi ormai. Nessun lato negativo in quanto tale per me. Nessun problema architettonico neanche. –

+0

Grazie amico, stavo considerando l'utilizzo di entrambi - ALB per la gestione socket e ELB per tutto il resto che ho utilizzato finora, ma non sono sicuro che valga la pena mantenere entrambi i valori – user3766930

4

Come ho detto nel post, usiamo solo ELB SSL terminare e di bilanciamento del carico su un cluster di server HTTP proxy che fanno WebSockets supporto. ELB non parla direttamente con i server Websocket. Il cluster di proxy HTTP gestisce la ricerca del server socket.io di destra da connettere per garantire la stickiness della sessione.

+0

Quindi non ci dovrebbero essere problemi se il proxy http è in esecuzione sugli stessi server dell'app socket.io? Sto pensando di utilizzare ELB per bilanciare tra un gruppo di server in esecuzione (-> http-proxy -> socket.io) –

15

Socket.io non funziona out of the box, anche con una rete TCP ELB perché fa due richieste HTTP prima di aggiornare il collegamento a WebSockets.

Il primo collegamento è utilizzato per stabilire il protocollo, in quanto socket.io supporta più di un semplice WebSockets.

GET /socket.io/1/?t=1360136617252 HTTP/1.1 
User-Agent: node-XMLHttpRequest 
Accept: */* 
Host: localhost:9999 
Connection: keep-alive 

HTTP/1.1 200 OK 
Content-Type: text/plain 
Date: Wed, 06 Feb 2013 07:43:37 GMT 
Connection: keep-alive 
Transfer-Encoding: chunked 

47 
xX_HbcG1DN_nufWddblv:60:60:websocket,htmlfile,xhr-polling,jsonp-polling 
0 

La seconda richiesta è utilizzato per aggiornare in realtà il collegamento:

GET /socket.io/1/websocket/xX_HbcG1DN_nufWddblv HTTP/1.1 
Connection: Upgrade 
Upgrade: websocket 
Sec-WebSocket-Version: 13 
Sec-WebSocket-Key: MTMtMTM2MDEzNjYxNzMxOA== 
Host: localhost:9999 

HTTP/1.1 101 Switching Protocols 
Upgrade: websocket 
Connection: Upgrade 
Sec-WebSocket-Accept: 249I3zzVp0SzEn0Te2RLp0iS/z0= 

si può vedere nell'esempio di cui sopra che xX_HbcG1DN_nufWddblv è una chiave condivisa tra le richieste. Questo è il problema. I ELB eseguono il routing round-robin, ovvero la richiesta di aggiornamento raggiunge un server che non ha partecipato alla negoziazione iniziale. In quanto tale, il server non ha idea di chi sia il client.

I dati di stato in memoria sono il nemico del bilanciamento del carico. Fortunatamente, socket.io supporta l'uso di Redis per archiviare i dati. Se condividi la tua connessione redis con più server, in sostanza condividono le sessioni di tutti i client.

Vedere la socket.io wiki page per i dettagli su come impostare Redis.

+0

ELB fa round robin? non proprio. Se le richieste provengono da un singolo IP, vengono reindirizzati allo stesso server. Questo è un problema che ho scoperto quando ho caricato i test. Ecco perché AWS suggerisce di avere proxy su VPC. https://www.stackdriver.com/elb-affinity-problems/ http://harish11g.blogspot.fr/2012/07/aws-elastic-load-balancing-elb-amazon.html (punto 9) – mruellan

+0

È ancora così? ELB ha un'opzione per la viscosità, potrebbe questo risolvere il problema? https://www.dropbox.com/s/scucxocqsw514ci/Screenshot%202014-03-31%2014.47.01.png – SteveEdson

+1

@SteveEdson ELB non ha un'opzione per la stickiness TCP purtroppo. –

0

Quando si esegue un server in una nuvola che ha un/reverse proxy di bilanciamento del carico, router ecc, è necessario configurarlo per funzionare correttamente, soprattutto quando si scala il server usare più istanze.

Uno dei vincoli che Socket.io, SockJS e le librerie simili hanno è che hanno bisogno di parlare continuamente con la stessa istanza del server. Funzionano perfettamente quando c'è solo 1 istanza del server.

Quando si ridimensiona l'app in un ambiente cloud, il bilanciamento del carico (Nginx nel caso di Cloud Foundry) prenderà il sopravvento e le richieste verranno inviate a diverse istanze causando la rottura di Socket.io.

Per aiutare in tali situazioni, i bilanciatori di carico hanno una funzione chiamata "sessioni appiccicose" alias "affinità di sessione". L'idea principale è che se questa proprietà è impostata, dopo la prima richiesta di bilanciamento del carico, tutte le richieste seguenti andranno alla stessa istanza del server.

In Cloud Foundry, le sessioni persistenti basate su cookie sono abilitate per le app che impostano il cookie jsessionid.

Nota: jsessionid è il nome del cookie comunemente utilizzato per tenere traccia delle sessioni nelle applicazioni Java/Spring. Cloud Foundry lo sta semplicemente adottando come cookie di sessione appiccicoso per tutti i framework.

Quindi, tutte le app devono fare è impostare un cookie con il nome jsessionid per rendere socket.io lavoro.

app.use (cookieParser); app.use (express.session ({store: sessionStore, chiave: 'jsessionid', secret: 'your secret here'}));

Quindi questi sono i passaggi:

espresso imposta un cookie di sessione con il nome jsessionid. Quando si connette socket.io, utilizza lo stesso cookie e raggiunge il bilanciamento del carico Il bilanciamento del carico lo instrada sempre sullo stesso server in cui è stato impostato il cookie. Se si utilizza il bilanciamento del carico dell'applicazione, le impostazioni della sessione di Appiccicose sono a destinazione gruppo livello

Problemi correlati