Sticky load balance with Apache HTTPD 2.2

Apache HTTPD 2.2 includes some interesting features for making a basic load balancer.

This configuration makes a sticky loadbalancer with 3 backend servers. It is not dependant on any specific configuration of the backend server such as JSESSIONID or PHPSESSIONID.
It will create a BALANCEID-cookie with a route to a backend server.



#You need at least these modules

#Header used for setting cookie

LoadModule headers_module ...

#Proxy

LoadModule proxy_module ...

LoadModule proxy_http_module ...

LoadModule proxy_balancer_module ...
#Set a cookie if BALANCER_ROUTE_CHANGED containing BALANCER_WORKER_ROUTE environment variable
Header add Set-Cookie "BALANCEID=hej.%{BALANCER_WORKER_ROUTE}e; path=/;" env=BALANCER_ROUTE_CHANGED
#Show balancer-manager
<Location /balancer-manager>
  SetHandler balancer-manager
  Order allow,deny
  Allow from all
</Location>
ProxyRequests Off
#Configure members for cluster
<Proxy balancer://jakeri>
  BalancerMember http://b1.jakeri.net:80 route=server1
  BalancerMember http://b2.jakeri.net:80 route=server2
  BalancerMember http://b3.jakeri.net:80 route=server3
</Proxy>
#Do not proxy balancer-manager
ProxyPass /balancer-manager !
#The actual ProxyPass
ProxyPass / balancer://jakeri/ stickysession=BALANCEID nofailover=Off
#Do not forget ProxyPassReverse for redirects
ProxyPassReverse / http://b1.jakeri.net/
ProxyPassReverse / http://b2.jakeri.net/
ProxyPassReverse / http://b3.jakeri.net/

I believe that this configuration is somewhat better compared to this guide.

I got to fix my css for the <code></code> :-/

Be Sociable, Share!

29 thoughts on “Sticky load balance with Apache HTTPD 2.2

  1. Mark

    Is there a typo in your post? You are setting the value for the cookie to:

    BALANCEID=hej.%{BALANCER_WORKER_ROUTE}e

    But your routes are specified as:

    route=server1
    route=server2
    route=server3

    And your stickiness is specified as the value of the cookie which won’t match the route values:

    stickysession=BALANCEID

    Mark

  2. admin Post author

    No. I don’t think so.

    I believe you are referring to the “hej.”-part. Take a look at mod_proxy (http://httpd.apache.org/docs/2.2/mod/mod_proxy.html#proxypass) documentation and you will see that the route-directive is “Route of the worker when used inside load balancer. The route is a value appended to session id.”.

    Take for instance a JSESSIONID-cookie for a tomcat. It usually look something like this JSESSIONID=42345234jfrfj4343.instance1, where the first part is the actual sessionid and the second part is the jvmroute set in server.xml.
    If you would use a tomcat you could just update the jvmroute in server.xml (in this example to server1, server2 and server3) for your servers and then change stickysession to JSESSIONID. No set header part needed at all.

    But sometimes you do not have good routing field set for each server or you are just lazy and want the proxy handle it.
    The httpd will elect one server based on the loadbalancing algorithm (default is byrequest) and set this value to the BALANCER_WORKER_ROUTE environment variable. If there is no cookie set (or a failure occurs) BALANCER_ROUTE_CHANGED will be 1 and write header SetCookie BALANCEID=hej.server1; path=/;. Next time when the same user arrives BALANCEID cookie is set and routed to server1.

    I hope my explanation was understandable. :-)

    Jakob

  3. igor

    Nice but I have one question: what will happen with the sticky sessions in case of backend server failure? Let’s say the apache receives a request with a cookie for server1 but the server1 is down? Will it continue sending the requests to the dead server because of the sticky session?

    Thanks,
    Igor

  4. admin Post author

    Hi Igor,

    If a backend server is down Apache proxy balancer will set BALANCER_ROUTE_CHANGED to a new server and the user will get a new BALANCEID-cookie.

    /Jakob

  5. alopez

    Can you easily make Cookies created on from the apache load balancer expire, say 5 minutes into the future?
    mod_rewrite appears to create Cookies that can expire in 5 minutes but can it utilize the environment variables you are using, e.g. BALANCER_WORKER_ROUTE?
    There are times where Cookies with a short life span can be advantageous.

  6. Dima

    Hi. Can you please explain where this section should be used:

    #Set a cookie if BALANCER_ROUTE_CHANGED containing BALANCER_WORKER_ROUTE environment variable
    Header add Set-Cookie “BALANCEID=hej.%{BALANCER_WORKER_ROUTE}e; path=/;” env=BALANCER_ROUTE_CHANGED

  7. Matt Weg

    Worked perfectly. I wan’t a big fan of the alternate method that used a RewriteRule on each of the cluster servers. Really glad you shared this!

    -Matt

  8. Jacek

    Hi

    I wonder if it is possible to balance&route with an own SessionID without appending the “.worker1″ to it. I have an Application(CRM) which has an IE Browser embedded in an IFrame this Application generates an own SessionID that I have to use while balancing. On the other side there is the Apache and some tomcats in the backend at the moment they are balanced by using their own JSessionID.worker1 . I would like to replace that with my own SessionID. Balancing works well now but I have no Session for my outside App because it is lost somewhere in the Apache or Tomcat.
    any suggestions ?

  9. Mustafa

    Hi,

    It is a good post in deed as i have been searching for such a post.
    I am a newbie to apache and have installed a zentyal server in my organisation.
    I am done with the mod_proxy module in order to redirect requests from my zentyal server (linkload balancer+firewall) to two webservers behind the zentyal however not able to implement mod_proxy_balancer so far :(
    i have some confusions here:
    1.what is this b1.jakeri.net, b2.jakeri.net etc.? webserver names? can i use webserver IPs instead?
    2.How can i install all the mentioned modules on zentyal (ubuntu base)?
    3.where do i have to implement the given code?…in a new virtual host or already created virtual host2 for webserver1 and webserver2?

    Hope you have understood my level of confusion!

    Regards

  10. Erix

    Thank you for this useful trick!
    I still don’t understand the “hej” part though…
    I suppose we can drop it in our case.

  11. admin Post author

    The sticky session proxypass only read the part after the dot in the cookie. Therefore you can write whatever you want instead of hej.

  12. Pingback: - Geek blog

  13. Rao

    Works like a Charm, I’m using SAP BI clusters servers with Apache balancers and the response is great. Thanks for this great post.

  14. Max

    Hey ! nice post.
    I was wondering how we can do this same configuration for the back end server which are using directory structure.
    servers:
    10..x.x.1 home/song1 ……song2 …song3 …..song10.
    10..x.x.2 home/song11 ……song12 …song13 …..song20.
    I want Sticky load balance these server as per the directory specified.
    for example if any third party want to put content which belongs to song dir 1 it should connect to song1 every time ..son2 dir for content related to song dir 2 and so on…

    Thank in advance !

  15. Pingback: Run several demos from one IP « 29min

  16. admin Post author

    Strange. It feels like b1 or b2 respond with absolute urls with the wrong name.
    Try to debug on a more low level and figure out what is exactly rewriting the urls.
    B1 and b2 should act as if they were called http://www.jakeri.net.

  17. Biggi

    I think the backend servers receive the hostname used in BalancerMember unless you use
    ProxyPreserveHost On

  18. Pingback: Balanceo de Carga con Apache 2.2 o superior, en Windows. | ıllıllı ·3KBZ ıllıllı

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>