Hi Willy,

I am using haproxy/rand to simulate A/B/C... testing between multiple
environments. Each backend emits a long expiry cookie to put the
session into their experiment. If a request comes with a cookie of the
experiment, the request goes to that backend. If a session comes
without a cookie, rand is used to decide which backend would be used
for the request.

My earlier code looked similar to

acl testa req.cookie(abtest) eq a
acl testb req.cookie(abtest) eq b
acl testa_rand rand(100) lt 80
acl testb_rand rand(20) lt 20
http-request set-header expirment=a if testa
http-request set-header expirment=b if testb

http-request set-header expirment=a if !testa !testb testa_rand
http-request set-header expirment=a if !testa !testb testb_rand

use_backend bk_a if testa
use_backend bk_b if testb
use_backend bk_a if testa_rand
use_backend bk_b if testb_rand

However, this config was failing as request would often to backend
with experiment header not set properly. Once I understood that acl
was evaluating rand every time, I was able to write the configuration
something like

http-request del-header experiment
http-request set-header experiment a if { req.cook(abtest) eq a }
http-request set-header experiment b if { req.cook(abtest) eq b } &&
!{ req.hdr(experiment) -m found }
http-request set-header experiment a if { rand(100) lt 80 } && !{
req.hdr(experiment) -m found }
http-request set-header experiment b if { rand(20) lt 20 } && !{
req.hdr(experiment) -m found }

use_backend bk_a if { req.hdr(experiment) eq a }
use_backend bk_b if { req.hdr(experiment) eq b }

Using the request header as a temporary variable, I was able to keep
state and avoid calling rand acl more than once.

Thanks,
Vivek

On Thu, Mar 5, 2015 at 12:55 AM, Willy Tarreau <[email protected]> wrote:
> Hi Vivek,
>
> On Sun, Mar 01, 2015 at 12:21:57AM -0600, Vivek Malik wrote:
>> Hi,
>>
>> I spent last few hours scratching my head and wondering where my
>> configuration was wrong and why was it acting weird. Sending this to
>> ML to see if this is a bug or expected behavior. I expected ACL to
>> evaluate its condition only once and store the true/false outcome,
>> however with rand(), I believe that ACL keeps re-evaluating on every
>> use. Example,
>>
>> acl random rand(50) lt 25
>> http-response set-header H1 V1 if random
>> http-response set-header H2 V2 if random
>> http-response set-header H3 V3 if random
>>
>> I would except either all 3 headers H1, H2, H3 to be set or none to be
>> set. However, in my test config I observed that H1, H2, H3 are set
>> independent of each other essentially meaning that ACL is getting
>> re-evaluated every time it is getting used.
>>
>> Is this the expected behavior of ACLs? If yes, how would using a named
>> ACL be different than using an anonymous ACL?
>
> It's normal and it works as expected (eventhough it doesn't match your
> expectations). ACLs are evaluated when they're used. So here what happens
> is that the random value is evaluated on each line.
>
> In practice we can find various ways to work around this depending on
> your use case. Could you please describe what you wanted to achieve,
> as I suspect that your config above was made only to confirm your
> observation, and is not related to your target use case ?
>
> Thanks,
> Willy
>

Reply via email to