WebSocket proxy support added to nginx trunk
trac.nginx.org
trac.nginx.org
One workaround that comes to mind is to have each backend listen on multiple ports.
You only need special tricks when you want to simulate a large number of client connections from a single machine (or bunch of machines). The client(s) have a requirement of a unique IP/source-port combination; not the server.
There is not a port limit issue, however, as nginx can create more than one connection to a local backend server using unix domain sockets. But the backend server has to then manage multiple open connections, as well, one for each WebSocket.
Normally I think it's best for HTTP backends to be stateless, but WebSockets open up interesting possibilities for RPC solutions like NowJS (https://github.com/Flotype/now), dnode (https://github.com/substack/dnode), and others (https://github.com/kriskowal/q-connection) that benefit from keeping state in memory in the app servers.
I'd be interested to hear about other load balancing techniques for WebSockets.
For the initial connection, you can use any of nginx's normal proxy load balancing options (ip_hash, least_conn, etc).
http://blog.exceliance.fr/2012/11/07/websockets-load-balanci...
dotCloud's Hipache also looks like it was basically written to solve this problem:
This is the main reason why WebSockets are not ready for production.
i've been working on an app recently that was (hoping) to implement websockets, but at this stage it seems xhr-polling is still the best bet...
There are libraries like SignalR that will try websockets, but fall back to long polling if the client does not suport it.
We're running an in-browser vt100 terminal, Tornado with a SockJS plugin on the backend, round-tripping every keystroke and output from the processes on the server and when SockJS uses WebSockets we get near-ssh responsiveness -- you can run vim just fine. Things are less good but still definitely usable (at least on the command line, vim can be a little frustrating) when it fails over to other protocols.
Also, IIRC the code we had to write to handle reconnects on patchy connections with SocketIO was pretty gruesome. The problem was that if the connection dropped, it would fail down from WebSockets through various polling systems (which is correct behaviour) but would then stop at the last failover option and never recover, even when the connection came back up. We poked around in the code trying to work out how to change this, but found it too confusing. SockJS didn't have this problem, and we also found the code a bit easier to read, at least from a fairly shallow overview.
I agree, having the power to write your proxy code in javascript is really nice, especially compared to having to struggle with getting some infrastructure's DSL to work for you (e.g. nginx, varnish's).
http://www.exratione.com/2012/07/proxying-websocket-traffic-...
http://www.exratione.com/2012/08/websockets-over-ssl-stunnel...
http://www.exratione.com/2012/12/websockets-over-ssl-haproxy...
"So let us say that you are developing a Node.js / Socket.IO application that both uses websockets and serves files the old-fashioned way, such as through Express - this is a fairly common situation. You want to have an HTTP proxy server rather than Node.js field all incoming traffic, so that you can set up load balancing, route requests for static files to some other server process, avoid having to set up SSL configuration in Node.js, and so forth.
"Unfortunately at this point in time it isn't completely straightforward to proxy both websocket traffic and ordinary web requests for Node.js through a single port - which would be the ideal situation. It becomes even less straightforward if you want to use SSL. The following is a brief overview of present options as of early Q3 2012."
"The up-front summary: if you are reading this after Nginx adds support for proxying websocket traffic to Node.js (supposedly coming up in version 1.3), then everything is rainbows and unicorns - just use Nginx. If you are reading this prior to Nginx support for proxying of websocket traffic, then you will likely have to do more work and investigation in order to create a good proxy setup for your servers."
Use cases of websockets enabled reverse proxies are for when you have a number of websockets based apps all sitting on the same box or in the same private local network and you need a way to route incoming traffic to them based on the hostname or path or whatever.
Will Nginx maintain a mapping table of client browser connection to Unicorn process, so that messages will always hit the same Unicorn process? Does that mean the Unicorn processes don't behave in a "stateless" manner?
Then what happens to the websocket if a Unicorn process dies and is restarted? What does the client browser do? What does Nginx do? What happens to the websocket connections if Nginx dies and there is a failover to a backup Nginx instance?
If your backend dies or drops the connection, the WebSocket closes, and the client will have to reconnect. If it was just dropped, you can use nginx's ip_hash proxy option to send the reconnect to the same backend server, but it would be a new WebSocket, and the client/server will have to recreate the session state.
The dev branch is officially upgraded to stable infrequently, maybe once a year.
https://launchpad.net/~chris-lea/+archive/nginx-devel
I've written up a very quick tutorial on how to set things up here:
https://chrislea.com/2013/02/23/proxying-websockets-with-ngi...
Hope people find these useful.
I'm using nginx and thin, but I'm currently having to use varnish for proxying my websocket connections to thin because nginx can't do it. Then I have to use stunnel for ssl termination because varnish doesn't support it. I'll be able to cut both of those pieces of software out now.
In the whole of my DevOps career, getting SSL working with web sockets was one of the most frustrating.
http://blog.jeffzellner.com/work/2013/01/25/websockets--ssl-...