Re: bug? rand based acl keep re-evaluating

2015-03-05 Thread Willy Tarreau
Hi Vivek,

On Thu, Mar 05, 2015 at 01:31:53AM -0600, Vivek Malik wrote:
> 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.

OK.

> 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

One possibility is also to use default_backend as a fallback. But
it would indeed not fix the multiple/missing header addition.

> 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.

Yes that definitely is the way to go.

Cheers,
Willy




Re: bug? rand based acl keep re-evaluating

2015-03-04 Thread Vivek Malik
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  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
>



Re: bug? rand based acl keep re-evaluating

2015-03-04 Thread Willy Tarreau
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




bug? rand based acl keep re-evaluating

2015-02-28 Thread Vivek Malik
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?

Regards,
Vivek