Search code examples
node.jswebsocketreverse-proxyhaproxy

HAProxy + WebSocket Disconnection


I am using HAProxy to send requests, on a subdomain, to a node.js app.

I am unable to get WebSockets to work. So far I have only been able to get the client to establish a WebSocket connection but then there is a disconnection which follows very soon after.

I am on ubuntu. I have been using various versions of socket.io and node-websocket-server. The client is either the latest versions of Safari or Chrome. HAProxy version is 1.4.8

Here is my HAProxy.cfg

global 
    maxconn 4096 
    pidfile /var/run/haproxy.pid 
    daemon 

defaults 
    mode http 

    maxconn 2000 

    option http-server-close
    option http-pretend-keepalive

    contimeout      5000
    clitimeout      50000
    srvtimeout      50000

frontend HTTP_PROXY
    bind *:80 

    timeout client  86400000

    #default server
    default_backend NGINX_SERVERS

    #node server
    acl host_node_sockettest hdr_beg(host) -i mysubdomain.mydomain

use_backend NODE_SOCKETTEST_SERVERS if host_node_sockettest


backend NGINX_SERVERS 
server THIS_NGINX_SERVER 127.0.0.1:8081

backend NODE_SOCKETTEST_SERVERS
timeout queue   5000
timeout server  86400000

server THIS_NODE_SERVER localhost:8180 maxconn 200 check

I've trawled the web and mailing list but can not get any of the suggested solutions to work.

(p.s. this could be for serverfault, but there are other HAProxy question on S.O, so I have chosen to post here)


Solution

  • Upgrade to latest version of socket.io (0.6.8 -> npm install socket.io@0.6.8, which is patched to work with HAProxy) and download the latest version of HAProxy.

    Here is an example config file:

    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 5000
        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 roundrobin
        option forwardfor # This sets X-Forwarded-For
        timeout server 5000
        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 roundrobin
        option forwardfor # This sets X-Forwarded-For
        timeout queue 5000
        timeout server 5000
        timeout connect 5000
        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