Bootstrap FreeKB - HAProxy (Load Balance) - Load Balance with Cookies and Sticky Sessions
HAProxy (Load Balance) - Load Balance with Cookies and Sticky Sessions


This assumes you have installed HAProxy.

Let's say you have two servers, www1.example.com and www2.example.com, and these servers both serve the www.example.com web pages. By default, HAProxy will use round robin to alternate the requests between www1.example.com and www2.example.com. Sticky Sessions can be used so that if a users first request hits www1.example.com, their subsequent requests will go to www1.example.com.

 


Listen Block

One option would be to use the listen block.

  • The prefer-last-server and cookie directives are used for sticky sessions. Replace "default-cookie" with anything you would like for the cookie name.
  • The httploghttp-request and log-format directives are not needed for sticky sessions, but are really helpful for debugging. Refer to HAProxy Logging for more details on logging.
listen web
    bind *:80
    mode tcp
    balance roundrobin
    option httplog
    http-request capture req.hdrs len 1024
    log-format "%ci:%cp [%tr] %ft [[%hr]] %hs %{+Q}r"
    option prefer-last-server
    cookie default-cookie prefix insert indirect nocache
    server www1 www1.example.com:80 check cookie www1
    server www2 www2.example.com:80 check cookie www2

 

If you have a firewall, such as iptables or firewalld, you will need to allow the HAProxy bind port, not the ports being used by the "server" directives. In this example, only the http (port 80) service would need to be allowed.

firewall-cmd --add-service=http --permanent
firewall-cmd --add-service=https --permanent
firewall-cmd --reload

 

SInce the httploghttp-request and log-format directives were included, the /var/log/haproxy.log should now show that the header contains the cookie (default-cookie in this example), something like this.

  • Notice in this example that default-cookie contains "www1". The prefix option is what includes the server (www1 in this example).
Feb 21 03:27:58 localhost haproxy[6083]: 192.168.0.104:59642 [21/Feb/2022:03:27:58.090] main 
[
 [
  {
   host: www.freekb.net
   cache-control: max-age=0
   upgrade-insecure-requests: 1
   user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.102 Safari/537.36
   accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
   referer: http://www.freekb.net/Article?id=12345
   accept-encoding: gzip, deflate
   accept-language: en-US,en;q=0.9
   default-cookie=www1
  }
 ]
]

 


Frontend / Backend

Or, the frontend and backend blocks can be used. However, this is more commonly used for more complex situations, such as when there are two web servers serving multiple domains.

hdr is short for HTTP headers. For example, the curl command can be used to see the "host" header.

~]$ curl http://www.freekb.net --verbose
> GET / HTTP/1.1
> Host: www.freekb.net
> User-Agent: curl/7.79.1
> Accept: */*

 

In this example

  • acl node hdr(host) -i node.freekb.net is used to route requests to the node backend when going to node.freekb.net (the -i flag means case insensitive)
  • the name of the cookie will be "sticky"
frontend main
    bind *:80
    bind *:443 ssl crt /etc/pki/tls/foo.pem
    balance roundrobin
    option prefer-last-server

    acl node hdr(host) -i node.example.com
    use_backend node if node

    default_backend node

backend stage
    cookie sticky insert indirect nocache
    server server1 10.0.0.1:12345 check cookie server1
    server server2 10.0.0.2:12345 check cookie server2

 

Let's say 10.0.0.1 is a Docker system that contains a NodeJS Express app that returns Hello World.

 

Likewise, let's say 10.0.0.2 is a Docker system that contains an identical NodeJS Express app that also returns Hello World.

 

Now when going to node.freekb.net the NodeJS Express app is returned from either server1 or server2.

 

And there should be a cookie named "sticky" (in this example) in your browser since we named our cookie in HAProxy "sticky". Notice also the request hit server1.

 

And /var/log/haproxy.log should now that the request hit server1.

May 26 03:45:35 localhost haproxy[30781]: 65.89.100.90:63361 [26/May/2024:03:45:35.640] my_domains~ node/server1 71/0/2/11/84 200 274 - - --NI 2/2/0/1/0 0/0 "GET / HTTP/1.1"

 

Now, if we reload the browser a few times, we should see that /var/log/haproxy.log shows that subsequent request remain on server1. Perfect!

May 26 03:51:12 localhost haproxy[30781]: 65.89.100.90:63609 [26/May/2024:03:51:10.938] my_domains~ node/server1 1285/0/1/2/1288 200 274 - - --VN 2/2/0/1/0 0/0 "GET / HTTP/1.1"
May 26 03:51:14 localhost haproxy[30781]: 65.89.100.90:63609 [26/May/2024:03:51:12.226] my_domains~ node/server1 2228/0/1/2/2231 200 274 - - --VN 2/2/0/1/0 0/0 "GET / HTTP/1.1"
May 26 03:51:15 localhost haproxy[30781]: 65.89.100.90:63609 [26/May/2024:03:51:14.458] my_domains~ node/server1 1524/0/1/3/1528 200 274 - - --VN 2/2/0/1/0 0/0 "GET / HTTP/1.1"
May 26 03:51:17 localhost haproxy[30781]: 65.89.100.90:63609 [26/May/2024:03:51:15.986] my_domains~ node/server1 1189/0/1/2/1192 200 274 - - --VN 2/2/0/1/0 0/0 "GET / HTTP/1.1"
May 26 03:51:18 localhost haproxy[30781]: 65.89.100.90:63609 [26/May/2024:03:51:17.178] my_domains~ node/server1 1060/0/1/3/1064 200 274 - - --VN 2/2/0/1/0 0/0 "GET / HTTP/1

 




Did you find this article helpful?

If so, consider buying me a coffee over at Buy Me A Coffee



Comments


Add a Comment


Please enter 0c5c0c in the box below so that we can be sure you are a human.