HAProxy URL + cookies Based routing with load balancing

I have 2 server witch run behind HaProxy Load balancer.

Here scenario is that application opens new popup window and it doesn’t carry forward parent cookies in pop up window, so it doesn’t know which back-end server will serve the request, so we have planned to pass it in URL like for initial request

Next request which comes after this will have the SERVERID as cookie, so here default haproxy backend will take care where to send the request

example. com/?balancer=app1 (This request should go to app1 server in backend)

OR

example. com/?balancer=app2 (This request should go to app2 server in backend)

I have 3 questions

  1. Is it possible using below Haproxy configuration ?

  2. How can I simplify this configuration ?

  3. if argument is in middle like http://example.com/?id=10&balancer=app2&product_id=110 , then what will be the conditional check in Haproxy configuration?

    frontend app-frontend
    bind 127.0.0.1:9005
    mode http
    acl app1_url urlp_reg(balancer) ^app1$
    acl app2_url urlp_reg(balancer) ^app2$
    use_backend app1_backend if app1_url
    use_backend app2_backend if app2_url
    default_backend app-backend

    backend app-backend
    mode http
    option httpclose
    balance leastconn
    cookie SERVERID insert indirect nocache
    server app1 10.168.1.10:80 check cookie app1
    server app2 10.168.1.20:80 check cookie app2

    backend app1_backend:
    mode http
    option httpclose
    balance leastconn
    cookie SERVERID insert indirect nocache
    server app1 10.168.1.10:80 check cookie app1

    backend app2_backend:
    mode http
    option httpclose
    balance leastconn
    cookie SERVERID insert indirect nocache
    server app2 10.168.1.20:80 check cookie app2

Hi Pankaj,

I have tested your configuration and it appears to be working fine. So to answer your questions:

Yes it is possible.
As described in your post, you intend to provide the cookie in Query String, only for the first request. All the subsequent requests thereafter have the cookie set in request header. Therefore to fulfill this requirement, you need to add a check in your haproxy configuration to validate the existence of a valid cookie in req header. If a valid cookie does not exist, in that case you need to consider the value provided in query string.
Below is the configuration file:

global
        log 127.0.0.1:514 local0
        chroot /var/lib/haproxy
        stats socket /run/haproxy/admin.sock mode 660 level admin
        stats timeout 30s
        user nobody
        group nobody
        daemon

defaults
        mode http
        log global
        option httplog
        option dontlognull
        timeout connect 5000
        timeout server 50000
        timeout client 50000

frontend fe
        bind *:80
        mode http
        acl has_cookie req.cook(SERVERID) -m found
        acl app1_url urlp_sub(balancer) app1
        acl app2_url urlp_reg(balancer) ^app2$
        use_backend app1_backend if app1_url !has_cookie
        use_backend app2_backend if app2_url !has_cookie
        use_backend app_backend if has_cookie
        default_backend app_backend

backend app1_backend
        balance roundrobin
        cookie SERVERID insert indirect nocache
        server test.example1.com 10.0.4.245:80 check cookie 1

backend app2_backend
        balance roundrobin
        cookie SERVERID insert indirect nocache
        server test.example2.com 10.0.4.246:80 check cookie 2

backend app_backend
        balance roundrobin
        cookie SERVERID insert indirect nocache
        server test.example1.com 10.0.4.245:80 check cookie 1
        server test.example2.com 10.0.4.246:80 check cookie 2

As shown in the screenshot below, the very first request lands on app1_backend/test.example1.com with NI flag, signifying that has_cookie ACL returned FALSE and app1_url returned TRUE. For all the subsequent requests, has_cookie ACL was TRUE (signified by VN flag) and never validated the app1_url ACL.

To answer your 2nd question:

This configuration appears perfectly fine to me. Can you please elaborate as to Why and What would you exactly like to simplify?

To answer your 3rd question:

You need not make any changes. The regular expression defined would match the balancer parameter even if its in the middle of the Query String. However, if you still face any issues with urlp_reg directive, you may try the urlp_sub directive, as described in the configuration above.

Hope this is helpful !

Thanks,
Shivharsh

Thanks a lot Shivharsh for your help !!

About the simplification of configuration: Here for each server we are adding backend like app1_backend , app2_backend and so on. So here instead of adding these backend can we solve this kind of scenario using one backend

Hi Pankaj,

Yes, you can very well achieve the scenario described by you using HAProxy. You need to use the use-server directive in your backend configuration as shown below:

frontend fe
        bind *:80
        mode http
	    acl has_cookie req.cook(SERVERID) -m found
        use_backend app_backend_nocook if !has_cookie
        use_backend app_backend if has_cookie
        default_backend app_backend

backend app_backend_nocook
        cookie SERVERID insert indirect nocache
        acl app1_url urlp_sub(balancer) app1
        acl app2_url urlp_sub(balancer) app2
        use-server test.example1.com if app1_url
        use-server test.example2.com if app2_url
        server test.example1.com 10.0.4.245:80 check
        server test.example2.com 10.0.4.246:80 check

backend app_backend
        balance roundrobin
        cookie SERVERID insert indirect nocache
        server test.example1.com 10.0.4.245:80 cookie 1 check
        server test.example2.com 10.0.4.246:80 cookie 2 check

Here, we have used two backends, one catering to the cookie based requests and the other handling the query string based requests. And in the later backend, we have used the use-server directive.

You may refer to the HAProxy documentation for further details on use-server directive.

Hope this is helpful!

Thanks,
Shivharsh

1 Like

Hi Shivharsh,

Thanks for the solution.
Today I learned some thing new about HAProxy !!

1 Like

Hi all,

i have a similar query.

i have two zones. each zone having a group of servers. I want HAproxy proxy to redirect request based on UI or any other http header information.

i can design a custom header based on user type/location. also differen uris can be designed to show user zone identity.

can some one tell me:

  1. if it is possible to be done using http hash redirects.
  2. if not, what are the workarounds??

thanks