Hi Martin,
On Thu, Feb 25, 2010 at 11:53:16AM +0800, Martin Aspeli wrote:
> Hi,
>
> We're contemplating a design where we'll have two servers, A and B. On
> each, we'll have 8 instances of our application running, on ports
> 8081-8088. This is mainly to effectively use multiple cores.
>
> The application uses cookie-based sessions. We are able to share session
> among the 8 instances on each machine, but not across the two machines.
>
> A is the master server, where an HAProxy instance will run. B is a
> slave. Eventually, we'll want to be able to fail HAProxy over to B, but
> let's not worry about that yet.
>
> So, what we'd like is this:
>
> - A request comes in to HAProxy on A
>
> - If it's an unknown user, HAProxy picks the least busy of the 16
> instances on either A or B. We'd probably use prefixed cookies, so the
> user would be "unknown" until they logged in.
>
> - If it's a known user that's previously been to A, HAProxy picks the
> least busy of the 8 instances on A
>
> - Ditto, if it's a known user that's previously been to B, HAProxy
> picks the least busy of the 8 instances on B
>
> Is this possible? I could imagine doing it with three HAProxy instances
> (so the first one picks the server and the second one picks the node),
> but that feels overly complex.
Well, your demand is already quite complex, which is proven by the number
of rules you gave above to explain what you want :-)
I see 3 backends in your description because you enumerate 3 algorithms :
- the least busy of the 16
- the least busy of the 8 A
- the least busy of the 8 B
The idea would then be to have a default backend which gets requests
without cookies, and one backend per other group. I don't know if you
consider that all 8 instances of one host are always in the same state
(up/down) or if they can be independant. Let's consider them independant
for now.
Also you must be very careful with your cookie in prefix mode : we have
to remove it in the two other backends before passing the request to the
server. However we don't want to stick on it otherwise the first server
of each farm would always get the connections. Thus, the idea is to set
the cookie in prefix mode but not assign any cookie to the servers. That
way no server will be found with that cookie value and the load balancing
will happen. However you must ensure that your servers will not set the
cookie again later, otherwise it will be sent without any prefix to the
client and the stickiness will be lost.
Another solution would be to simply use cookie insertion mode. That way
you don't have to worry whether your application will set the cookie
again or not.
frontend www
acl a_is_ok nbsrv(bk_a) gt 0
acl b_is_ok nbsrv(bk_b) gt 0
acl cook_a hdr_sub(cookie) SRV=A
acl cook_b hdr_sub(cookie) SRV=B
use_backend bk_a if a_is_ok cook_a
use_backend bk_b if b_is_ok cook_b
default_backend bk_all
backend bk_all
# cookie-less LB, or catch-all for dead servers
balance leastconn
cookie SRV prefix
# or use this one : cookie SRV insert indirect nocache
option redispatch
server srv_a_1 1.1.1.1:8081 cookie A track bk_a/srv_a_1
...
server srv_a_8 1.1.1.1:8088 cookie A track bk_a/srv_a_8
server srv_b_1 1.1.1.2:8081 cookie B track bk_a/srv_b_1
...
server srv_b_8 1.1.1.2:8088 cookie B track bk_a/srv_b_8
backend bk_a
# Cookie: SRV=A
balance leastconn
option redispatch
server srv_a_1 1.1.1.1:8081 check
...
server srv_a_8 1.1.1.1:8088 check
backend bk_b
# Cookie: SRV=B
balance leastconn
option redispatch
server srv_b_1 1.1.1.2:8081 check
...
server srv_b_8 1.1.1.2:8088 check
I strongly suggest to enable the stats page on such a config
because it will not be easy to understand well in the first
tests.
Regards,
Willy