Forum Discussion

Kris__109062's avatar
Kris__109062
Icon for Nimbostratus rankNimbostratus
Jun 16, 2008

Odd results with iRule on virtual server selecting random pool member

Hi,

 

 

I have the following iRule setup on a Virtual Server of Type "Standard" using the "TCP" profile which has a custom Source Address Affinity persistence profile with a timeout of 1800 seconds using the parent profile source_address

 

 

If someone externally hits the VirtualServer with ?rand=true in the URI the irule is executed. The problem is that the first log to local0 of "accepted" only ever gets added to the logs if the 2nd request is > 15secs.

 

 

So the first request gets logged..

 

 

Jun 16 13:31:13 tmm tmm[1678]: Rule bookings_rand_node : accepted

 

Jun 16 13:31:13 tmm tmm[1678]: Rule bookings_rand_node : rand= found

 

 

BUT subsequent requests made again in < 15 seconds do not log ANYTHING. If I refresh again with a wait > 15 seconds the rule works.

 

 

Any ideas ?

 

 

The iRule follows..

 

 

when CLIENT_ACCEPTED {

 

if { [TCP::local_port] == 80 } {

 

log local0. "accepted"

 

TCP::collect 100

 

}

 

}

 

when CLIENT_DATA {

 

if { [ findstr [TCP::payload] "rand=" 5 4] equals true} {

 

set daStr [ findstr [TCP::payload] "rand=" 5 4]

 

log local0. "rand= found"

 

if { $daStr equals "true" } {

 

set cserver [lindex [active_members -list pool_bookings] [expr {int(rand()*[active_members pool_bookings])}]]

 

set ip [lindex $cserver 0]

 

pool pool_bookings member $ip

 

persist none

 

}

 

}

 

}

 

 

Also does anyone know a way using the rule above to find the default pool to the current virtual server so that I can apply this rule to other virtual servers without having to modify the pool name ?

 

 

[glynnk@ISKEF51:Active] ~ bp version

 

Kernel:

 

Linux 2.4.21-9.4.4.65.0smp

 

Package:

 

BIG-IP Version 9.4.4 65.1

 

Final Edition

 

 

Cheers

 

Kris
  • hoolio's avatar
    hoolio
    Icon for Cirrostratus rankCirrostratus
    You can get the default pool in CLIENT_ACCEPTED using 'set default_pool [LB::server pool]'. It sounds like the first request works, but subsequent requests on the same TCP connection don't. It might work after the current TCP connection closes and a new one is opened. I think this is expected, as you're only triggering the collection of the payload once per TCP connection.

     

     

    What layer 7 protocol are you using? Is the "uri" HTTP or some other protocol? Are there multiple requests on the same TCP which need to be load balanced to a potentially new pool member?

     

     

    Aaron
  • hoolio's avatar
    hoolio
    Icon for Cirrostratus rankCirrostratus
    If it's not HTTP, and there are multiple payloads you want to collect, can you try this?

     
     when CLIENT_ACCEPTED { 
        if { [TCP::local_port] == 80 } { 
           log local0. "accepted" 
           TCP::collect 100 
        } 
     } 
     when CLIENT_DATA { 
        if { [ findstr [TCP::payload] "rand=" 5 4] equals true} { 
           set daStr [ findstr [TCP::payload] "rand=" 5 4] 
           log local0. "rand= found" 
           if { $daStr equals "true" } { 
              set cserver [lindex [active_members -list pool_bookings] [expr {int(rand()*[active_members pool_bookings])}]] 
              set ip [lindex $cserver 0] 
              pool pool_bookings member $ip 
              persist none 
              TCP::release 
              TCP::collect 
           } 
        } 
     } 
     

    Aaron
  • Hi,

    Thanks for the tip on getting the default pool for a virtual server.

    I managed to sort this issue out by using a smaller byte parameter (50 bytes not 100 bytes) with TCP:collect

       
     when CLIENT_ACCEPTED { 
             if { [TCP::local_port] == 80 } { 
                      set default_pool [LB::server pool] 
                      TCP::collect 50 
             } 
     } 
     when CLIENT_DATA { 
                     if { [ findstr [TCP::payload] "rand=" 5 4] equals true} { 
                         set daStr [ findstr [TCP::payload] "rand=" 5 4] 
                         log local0. "rand= found" 
                         if { $daStr equals "true" } { 
                              set cserver [lindex [active_members -list $default_pool] [expr {int(rand()*[active_members $default_pool])}]] 
                              set ip [lindex $cserver 0] 
                              pool $default_pool member $ip 
                              persist none 
                         } 
                      } 
     }