Re: Being sticky to a host, but not to a port

From: Willy Tarreau <w#1wt.eu>
Date: Thu, 25 Feb 2010 10:16:31 +0100


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 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 Received on 2010/02/25 10:16

This archive was generated by hypermail 2.2.0 : 2010/02/25 10:30 CET