HAProxy is an open source load balancer, capable of balancing any TCP based service. It’s commonly used for balancing HTTP, and can help solve traffic problems on your web server. Here’s how to set it up.
What Is HAProxy?
Load balancers like HAProxy allow you to split traffic over multiple servers, making it easier to handle. Instead of pointing your IP at your web server, you’d point it at an HAProxy server, which would decide where to send it from there. HAProxy is very lightweight, and doesn’t need a lot of resources to operate, so you can use a single load balancer for many backend servers. Ideally, you want both your HAProxy server and your web servers to be hosted in the same datacenter, from the same cloud provider, to cut down on latency.
HAProxy also allows your network to be more resilient. If one web server goes down, HAProxy can route traffic to the rest while you diagnose the issue. For it to be truly resilient, you’ll want to have a backup HAProxy server, in case your load balancer goes down.
Even with HAProxy, you’ll still often want a full site CDN in front of it, both to handle additional load and to have multiple points of presence closer to the end user.
How To Set Up HAProxy Load Balancing
First, install HAProxy from your distro’s package manager. For Debian based systems like Ubuntu, that would be:
Next, you’ll need to turn it on by editing the init script at /etc/default/haproxy and setting ENABLED to 1:
Now, if you run service haproxy, you should see that it is enabled and ready to be configured. We’ll start by archiving the default configuration file:
Create a new config file in its place, and start by adding a few global settings:
The log setting specifies the syslog server that HAProxy sends logs to. You’ll need to have a server like rsyslog running to make use of this. The maxconn setting specifies the max concurrent connections, and user and group specify which Unix user HAProxy operates as.
The last few lines turn on HAProxy’s built in statistics page, which you can view by navigating to the URI in your browser. In this case, that would be http://your_ip/haproxy?stats, but you can view a demo of it here.
Next, we’ll set the default config that will apply to all listen blocks if they don’t make any changes to it:
We’re setting the default to use the global log setting, operate on HTTP, and set some settings related to connection timeouts.
We’ll create a frontend block that will do the heavy lifting, and forward connections to the backend:
The first line binds this frontend to port 80, where HAProxy will listen on.
The next two sections are for rate limiting. First, the access control list (ACL) functions are declared, which determine if an IP address is abusive. Then, a set of rules will reject a connection if it’s making too many requests.
The forwardfor option will forward the client’s IP address to the server. Since HAProxy acts as a reverse proxy, your nginx server would only see your HAProxy server’s IP address. This option sets the X-Forwarded-For HTTP header to the client’s IP address.
And finally, we set this frontend block to use the backend “appname,” which we’ll need to create. The backend block simply defines the servers to forward to, along with a few options:
The balance directive defines how HAProxy balances requests between servers. The most common option is roundrobin, which will rotate connections through each server in order. If you run into issues with balance, you can try using the option leastconn, which selects based on concurrent connections. If you need users to access the same server over multiple connections, you can use the source option, which selects based on a hash of the client’s IP address.
The last two lines allocate servers to this listen block. You give them a name (web1 and web2) specify their addresses, and then list a few options. Here, we use the check parameter to make sure the server is healthy and accepting connections, and the cookie parameter to set the SERVERNAME cookie (which we inserted directly above) to the name of the server, which is used for session stickiness (so the user doesn’t switch servers while using your site). The balance source option achieves this same effect.
And because we’re using rate limiting, we’ll actually need another backend to store IP addresses:
This doesn’t actually forward any connections; it functions as a table to store addresses in. Addresses are flushed after 30 minutes, so addresses deemed abusive will be blocked for 30 minutes.
Finally, you can start the HAProxy service by running: