WebSockets and SSL

Some time ago one of our clients requested SSL support in application. This would be nothing special, but some part of the application is using Websockets (Socket.IO to be precise). Due to fact that Nginx doesn’t support websockets in standard installation, we had to find another way to proxy SSL requests.

There were three main proposals:

  • Patch and compile Nginx with tcp module
  • Add STunnel to the configuration
  • Use Development version of HAProxy with SSL

First two solutions were making our infrastructure more complex:

First required maintaing new package, and was obsoleting the HAProxy configuration, which we didn’t want to get rid of due to high availability (and yes we’re aware of Nginx http proxy capabilities).

Second one was adding another layer to the infrastructure which is one more to debug in case of problems.

The third one, using HAProxy, was simple and clean:

bind 0.0.0.0:443 /path/to/ssl.pem
acl is_websocket path_reg ^/socket.io/.*$
use_backend nginx if !is_websocket 
use_backend socket_io if is_websocket

UPDATE (2013.03.01) There’s a 4th option available as NGINX from version 1.3.13 supports Websockets natively

Advertisement
Quote

HAProxy running on virtualized environment…

When HAProxy is deployed on VM (such as linode.com) the performance can be decreased even more than 50%. The story behind such behavior is that the packet must be forwarded from HV to VM. Such operations are always heavy (packet is copied into memory, NIC send the interupt, which interrupts VM to HV kernel…) Worst case scenario is when one is using NAT instead of bridged interfaces.

What can you do to get better performance?

First of all understand the kernel parameters and tune them. Below you can find 2 which can have serious impact on number of processed requests:

/proc/sys/net/netfilter/nf_conntrack_tcp_timeout_time_wait (as Willy Tarreau sugests set it to 30secs)

/proc/sys/net/netfilter/nf_conntrack_max

Then go to HAProxy configuration and add

option tcp-smart-accept
option tcp-smart-connect

and restart your instance.

Note that both options are available from HAProxy 1.4

Here you can find more comments on the issue.

HAProxy running on virtualized environment…