Re: bug? rand based acl keep re-evaluating
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
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
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
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