haproxy is one of the best known and widely used Open Source load balancers out there and a strong competitor to nginx.
haproxy is used by many large sites per Wikipedia:
HAProxy is used by a number of high-profile websites including GoDaddy, GitHub, Bitbucket,[6] Stack Overflow,[7] Reddit, Slack,[8] Speedtest.net, Tumblr, Twitter[9][10] and Tuenti[11] and is used in the OpsWorks product from Amazon Web Services.[12]
According to some stats data haproxy is even more popular than the AWS Elastic Load Balancer:
apt install haproxy
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following packages were automatically installed and are no longer required:
acl ebtables galera-3 git git-man iproute2 less libatm1 libconfig-inifiles-perl libdbd-mysql-perl libdbi-perl liberror-perl libjemalloc1 liblzo2-2 libuv1 lsof
mariadb-common netcat netcat-traditional patch pigz runc socat squashfs-tools ubuntu-fan xdelta3
Use 'apt autoremove' to remove them.
Suggested packages:
vim-haproxy haproxy-doc
The following NEW packages will be installed:
haproxy
0 upgraded, 1 newly installed, 0 to remove and 34 not upgraded.
Need to get 1116 kB of archives.
After this operation, 2374 kB of additional disk space will be used.
Get:1 http://archive.ubuntu.com/ubuntu bionic-updates/main amd64 haproxy amd64 1.8.8-1ubuntu0.13 [1116 kB]
Fetched 1116 kB in 2s (657 kB/s)
perl: warning: Setting locale failed.
perl: warning: Please check that your locale settings:
LANGUAGE = (unset),
LC_ALL = (unset),
LANG = "C.UTF-8"
are supported and installed on your system.
perl: warning: Falling back to the standard locale ("C").
locale: Cannot set LC_CTYPE to default locale: No such file or directory
locale: Cannot set LC_MESSAGES to default locale: No such file or directory
locale: Cannot set LC_ALL to default locale: No such file or directory
Selecting previously unselected package haproxy.
(Reading database ... 20143 files and directories currently installed.)
Preparing to unpack .../haproxy_1.8.8-1ubuntu0.13_amd64.deb ...
Unpacking haproxy (1.8.8-1ubuntu0.13) ...
Setting up haproxy (1.8.8-1ubuntu0.13) ...
Created symlink /etc/systemd/system/multi-user.target.wants/haproxy.service → /lib/systemd/system/haproxy.service.
invoke-rc.d: could not determine current runlevel
invoke-rc.d: WARNING: No init system and policy-rc.d missing! Defaulting to block.
Processing triggers for systemd (237-3ubuntu10.57) ...
vi /etc/haproxy/haproxy.cfg
Here is how the defaults of haproxy.cfg look:
global
log /dev/log local0
log /dev/log local1 notice
chroot /var/lib/haproxy
stats socket /run/haproxy/admin.sock mode 660 level admin expose-fd listeners
stats timeout 30s
user haproxy
group haproxy
daemon
# Default SSL material locations
ca-base /etc/ssl/certs
crt-base /etc/ssl/private
# Default ciphers to use on SSL-enabled listening sockets.
# For more information, see ciphers(1SSL). This list is from:
# https://hynek.me/articles/hardening-your-web-servers-ssl-ciphers/
# An alternative list with additional directives can be obtained from
# https://mozilla.github.io/server-side-tls/ssl-config-generator/?server=haproxy
ssl-default-bind-ciphers ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:RSA+AESGCM:RSA+AES:!aNULL:!MD5:!DSS
ssl-default-bind-options no-sslv3
defaults
log global
mode http
option httplog
option dontlognull
timeout connect 5000
timeout client 50000
timeout server 50000
errorfile 400 /etc/haproxy/errors/400.http
errorfile 403 /etc/haproxy/errors/403.http
errorfile 408 /etc/haproxy/errors/408.http
errorfile 500 /etc/haproxy/errors/500.http
errorfile 502 /etc/haproxy/errors/502.http
errorfile 503 /etc/haproxy/errors/503.http
errorfile 504 /etc/haproxy/errors/504.http
More info about configuring haproxy from the authors.
Let's add a frontend and backend
At the moment the load balancer does nothing and essentially has no usable configuration. We're going to add a frontend that listens on localhost and is bound to port 8080.
The frontend itself is just the entry point for the user, the frontend is configured on a certain IP and port that we define and the next step is that we'll have to define a "backend" that is the actual source server (eg. our Apache running PHP or another application)
Add this frontend and backend config to the end of haproxy.cfg
frontend rttfrontend
bind 0.0.0.0:8080
default_backend rttbackendservers
backend rttbackendservers
server backendserver01 127.0.0.1:80
cache rttcache
# Total size of the cache in MB
total-max-size 500
# Max size of any single item in bytes
max-object-size 100000
# Time to live for each item in seconds
# This can be overridden with a Cache-Control header
max-age 3000
This config allows you to scale out as much as you need, for example you could add dozens or hundreds of backend servers with different IPs and ports.
You may also want to add the "check" option after each server so requests won't be sent to dead or overloaded servers:
server rttbackendserver01 server.com:9000 check
We can make it more like a CDN by enabling cache, so the backend servers don't need to be contacted if we have a cache hit:
cache rttcache
# Total size of the cache in MB
total-max-size 500
# Max size of any single item in bytes
max-object-size 10000
# Time to live for each item in seconds
# This can be overridden with a Cache-Control header
max-age 3000
In older versions like 1.8, the max-object-size option does not exist.
You'll find the cache doesn't work unless you set this option in your global config:
tune.bufsize 9999999
In our first example below the page in question has not been cached and has a TTFB of 0.486955 seconds and total load time of .677587 seconds.
curl -k -o /dev/null -w "Connect: %{time_connect} TTFB: %{time_starttransfer} Total time: %{time_total} \n" $site
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 16413 100 16413 0 0 24243 0 --:--:-- --:--:-- --:--:-- 24207
Connect: 0.047765 TTFB: 0.486955 Total time: 0.677587
Now after we loaded the site and it is in the cache notice the difference in performance:
TTFB is now 0.090424 and total load time of .135752
TTFB is now 5.38X faster and load time was 4.99X faster!
curl -k -o /dev/null -w "Connect: %{time_connect} TTFB: %{time_starttransfer} Total time: %{time_total} \n" $site
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 16413 100 16413 0 0 118k 0 --:--:-- --:--:-- --:--:-- 118k
Connect: 0.044437 TTFB: 0.090424 Total time: 0.135752
By enabling stats we can check on things like how our cache is doing:
Add this to the globa section:
stats socket ipv4@127.0.0.1:9999 level admin
stats socket /var/run/hapee-lb.sock mode 666 level admin
You can echo commands via socat to see the status of things like you cache:
echo "show cache" | socat stdio /var/run/hapee-lb.sock
0x7f5f1ef9503a: rtt (shctx:0x7f5f1ef95000, available blocks:512000)
0x7f5f1ef950ac hash:3598866029 size:16657 (17 blocks), refcount:0, expire:25695
Here is a list of commands that can be sent:
echo "help" | socat stdio /var/run/hapee-lb.sock
Unknown command. Please enter one of the following commands only :
help : this message
prompt : toggle interactive mode with prompt
quit : disconnect
show tls-keys [id|*]: show tls keys references or dump tls ticket keys when id specified
set ssl tls-key [id|keyfile]
show errors : report last request and response errors for each proxy
disable agent : disable agent checks (use 'set server' instead)
disable health : disable health checks (use 'set server' instead)
disable server : disable a server for maintenance (use 'set server' instead)
enable agent : enable agent checks (use 'set server' instead)
enable health : enable health checks (use 'set server' instead)
enable server : enable a disabled server (use 'set server' instead)
set maxconn server : change a server's maxconn setting
set server : change a server's state, weight or address
get weight : report a server's current weight
set weight : change a server's weight (deprecated)
show sess [id] : report the list of current sessions or dump this session
shutdown session : kill a specific session
shutdown sessions server : kill sessions on a server
clear table : remove an entry from a table
set table [id] : update or create a table entry's data
show table [id]: report table usage stats or dump this table's contents
clear counters : clear max statistics counters (add 'all' for all counters)
show info : report information about the running process
show stat : report counters for each proxy and server
show schema json : report schema used for stats
show startup-logs : report logs emitted during HAProxy startup
show resolvers [id]: dumps counters from all resolvers section and
associated name servers
set maxconn global : change the per-process maxconn setting
set rate-limit : change a rate limiting value
set severity-output [none|number|string] : set presence of severity level in feedback information
set timeout : change a timeout setting
show env [var] : dump environment variables known to the process
show cli sockets : dump list of cli sockets
show fd [num] : dump list of file descriptors in use
show activity : show per-thread activity stats (for support/developers)
disable frontend : temporarily disable specific frontend
enable frontend : re-enable specific frontend
set maxconn frontend : change a frontend's maxconn setting
show servers state [id]: dump volatile server information (for backend
show backend : list backends in the current running config
shutdown frontend : stop a specific frontend
set dynamic-cookie-key backend : change a backend secret key for dynamic cookies
enable dynamic-cookie backend : enable dynamic cookies on a specific backend
disable dynamic-cookie backend : disable dynamic cookies on a specific backend
show cache : show cache status
add acl : add acl entry
clear acl
del acl : delete acl entry
get acl : report the patterns matching a sample for an ACL
show acl [id] : report available acls or dump an acl's contents
add map : add map entry
clear map
del map : delete map entry
get map : report the keys and values matching a sample for a map
set map : modify map entry
show map [id] : report available maps or dump a map's contents
show pools : report information about the memory pools usage
install, configure, haproxy, linux, ubuntu, debianhaproxy, widely, balancers, competitor, nginx, aws, balancer, apt, lists, dependency, packages, automatically, installed, acl, ebtables, galera, git, iproute, libatm, libconfig, inifiles, perl, libdbd, mysql, libdbi, liberror, libjemalloc, liblzo, libuv, lsof, mariadb, netcat, pigz, runc, socat, squashfs, xdelta, autoremove, vim, upgraded, newly, kb, archives, additional, disk, http, archive, bionic, updates, amd, fetched, locale, settings, unset, lc_all, lang, quot, utf, supported, lc_ctype, default, directory, lc_messages, selecting, previously, unselected, database, directories, currently, preparing, unpack, haproxy_, _amd, deb, unpacking, symlink, etc, systemd, multi, user, rarr, lib, invoke, rc, determine, runlevel, init, defaulting, processing, triggers, cfg, vi, defaults, global, dev, chroot, var, stats, socket, admin, mode, fd, listeners, timeout, daemon, ssl, locations, ca, certs, crt, ciphers, enabled, sockets, https, hynek, articles, hardening, servers, directives, obtained, mozilla, github, io, server, tls, config, generator, bind, ecdh, aesgcm, dh, aes, rsa, anull, md, dss, sslv, httplog, dontlognull, errorfile, errors, info, configuring, authors, frontend, backend, essentially, usable, configuration, listens, localhost, entry, configured, ip, define, ll, eg, apache, php, rttfrontend, default_backend, rttbackendservers, backendserver, allows, dozens, ips, ports, cdn, enabling, cache, contacted, rttcache, mb, bytes, overridden, header,