2011-11-16 16 views
5

Tengo varias instancias de socket.io con autenticación ejecutándose bajo HAProxy y necesito forzar que la solicitud de autenticación y la conexión de socket vayan a la misma instancia. He creado HAProxy basado en this answer to a SO question con algunas modificaciones como así:¿Puedo tener sesiones fijas con HAProxy y socket.io con autenticación?

global 
    maxconn  4096 # Total Max Connections. This is dependent on ulimit 
    nbproc  2 

defaults 
    mode  http 

frontend all 0.0.0.0:80 
    timeout client 86400000 
    default_backend www_backend 
    acl is_websocket hdr(Upgrade) -i WebSocket 
    acl is_websocket hdr_beg(Host) -i ws 

    use_backend socket_backend if is_websocket 

backend www_backend 
    balance url_param sessionId 
    option forwardfor # This sets X-Forwarded-For 
    timeout server 30000 
    timeout connect 4000 
    server server1 localhost:8081 weight 1 maxconn 1024 check 
    server server2 localhost:8082 weight 1 maxconn 1024 check 
    server server3 localhost:8083 weight 1 maxconn 1024 check 

backend socket_backend 
    balance url_param sessionId 
    option forwardfor # This sets X-Forwarded-For 
    timeout queue 5000 
    timeout server 86400000 
    timeout connect 86400000 
    server server1 localhost:8081 weight 1 maxconn 1024 check 
    server server2 localhost:8082 weight 1 maxconn 1024 check 
    server server3 localhost:8083 weight 1 maxconn 1024 check 

que he probado url_param (donde sessionId es un parámetro de cadena de consulta aprobada en tanto la llamada de autenticación y la conexión WebSocket) y la fuente como el equilibrio opciones pero parece que HAProxy solo permite estas opciones para las conexiones HTTP y, por lo tanto, las ignora para la conexión websocket real. El resultado es que a veces la solicitud de autenticación y la conexión del socket terminan en diferentes servidores, lo cual es inaceptable para nuestra aplicación.

¿Hay alguna manera de tener este comportamiento deseado?

+0

¿Alguna vez de averiguar la mejor manera de hacer esto? Estaba buscando hacer lo mismo. Gracias. –

+0

Terminé usando el equilibrio IP-hash. Todas las solicitudes de la misma IP van al mismo servidor – Diego

+0

O ok, pero ¿eso significa que un websocket que se transmite desde un usuario en el servidor A no llega a ninguno de los usuarios en el servidor B? –

Respuesta

0

Para conexiones de conexiones web usando roundrobin. Dado que es una adherencia bidireccional (a través de TCP), la adherencia se mantiene de forma predeterminada. Para otros transportes que usan source el algoritmo de equilibrio es la mejor opción. (Puede utilizar la persistencia basada en cookies, pero socket.io no envía una JSESSIONID o similar, de vuelta al servidor proxy puede tratar sockjs si quieres persistencia basada en cookies..)

Ejemplo:

#do the same for other transports. [Note in 0.6.x resource was mounted at path: /socket.io/[transport] 
acl is_JSONPolling path_beg /socket.io/1/jsonp-polling 
use_backend non_websocket if is_JSONPolling 


backend non_websocket 
    balance source 
    #rest same as the one for websocket backend 
+0

El problema es que la solicitud de autenticación y la conexión de websocket pueden terminar en servidores diferentes. ¿Hay alguna forma de hacer que siempre vayan al mismo servidor? ¿Sabría si otro equilibrador de carga lo proporciona? – Diego

+0

No importa qué servidor se golpea siempre que su tienda de autenticación esté separada de la aplicación. Con suerte, no está utilizando la memoria como su tienda para las sesiones de autenticación. Use algo como Redis para almacenar la clave de autenticación. Eche un vistazo a mi respuesta aquí para manejar auth: http://stackoverflow.com/questions/4753957/socket-io-authentication/4754806#4754806 –

2

Para equilibrar la conexión TCP, puede tener cierto éxito con una tabla de rigidez utilizando los comandos stick_match o stick on y estableciendo explícitamente el modo tcp.

Aquí se muestra un ejemplo:

# forward SMTP users to the same server they just used for POP in the 
# last 30 minutes 
backend pop 
    mode tcp 
    balance roundrobin 
    stick store-request src 
    stick-table type ip size 200k expire 30m 
    server s1 192.168.1.1:110 
    server s2 192.168.1.1:110 

backend smtp 
    mode tcp 
    balance roundrobin 
    stick match src table pop 
    server s1 192.168.1.1:25 
    server s2 192.168.1.1:25 

documentación completa disponible here.

9

que utiliza el equilibro basan en cookies de esta manera:

backend socketio 
    mode http 
    cookie SIO insert 
    server sock1 127.0.0.1:8001 cookie 001 
    server sock2 127.0.0.1:8002 cookie 002 
+0

Para el método de cookie, ¿hay alguna manera de establecer el tiempo de espera de la cookie? – Alessandro

0

Estás usando HTTP de modo insertar una cookie para la persistencia - que es sin duda la mejor ruta. Eso se pegará al primer servidor al que fueron, a menos que esté abajo.

También puede configurar si debe reexpedición si está abajo, etc.