Forum Discussion

Matt_Breedlove_'s avatar
Matt_Breedlove_
Icon for Nimbostratus rankNimbostratus
Jun 24, 2009

single VS distributing new connections across multiple pools with persistence

We have a single VS in standard mode with 2 pools of servers. Each pool contains different servers.

VS has cookie insert persistence with named cookie and a 17min timeout.

Goal is to have 1 out of every X number of NEW connections only go to the second pool. Once a client has been sent to the second pool, the subsequent requests from that user should also follow into the the second pool if during same session.

We have a single global variable that increments each time HTTP_REQUEST occurs, but we want to modify this so that it only increments on new connections

Current rule:

   
 when RULE_INIT {   
     set ::cnt 0   
 }   
 when HTTP_REQUEST {   
     incr $cnt   
     if { $cnt = 4000 } {   
         set ::cnt 0   
         pool pool2   
     } else {   
       pool $pool1   
     }   
 }   
 

Pool 2 is about 20% of the capacity of Pool 1 and using different class of server hardware.

One thing that I was thinking of was to look for the named persistence cookie, and if it does not already exist then increment the global var

The assumption is that new/initial HTTP connections can be identified in the VS's iRule by looking for the presence of the named inserted cookie via the persistence profile.

We have the megaproxy issue so we are dependent on cookie inserted persistence

Possible changed rule

   
 when RULE_INIT {   
     set ::cnt 0   
 }   
 when HTTP_REQUEST {   
     if { ([HTTP::cookie] exists "namedcookie_from_persistence_profile") } {     
         send connection to existing persisted server in whichever pool its in   
         Can 'persist' just be used or does the member and pool need to be looked up and then    
         manually pooled there?   
     } else {   
          Assumption is only brand new initial connections with no persistence yet defined are    
          being dealt with at this point   
         incr $cnt   
         if { $cnt = 4000 } {   
             set ::cnt 0   
             pool pool2 New persistence record is formed after this 'pool'   
         } else {   
             pool $pool1   
         } 
     }   
 }   
 

Is this the right strategy?

Can 'persist' be used in place of 'pool' to make sure the specific member in the respective pool is reused for the rest of that sessions http requests? Or is 'pool' required to actually farm the connection out

What we are trying to avoid is having User Bob come in and hit homepage on global var cont 3998, go to a server in pool a, then click on 2 links and the second link sets the global var to 4000, which causes Bob to have his second click "pooled" to the second pool. Rather we would not want User Bob's subsequent http requests to be capable of incrementing that global var, so that when User Joe comes in on new connection and he trips the counter to 4000, then his requests and subsequent requests in same connection/session go to that same node in the second pool

Once the persistence cookie expires then the user can be sent to either of the pools.

If the node in the pool is marked down by a monitor, we would expect that to wipe out the named persistence cookie causing them to be free to be subject to new pool and new subsequent persistence record being created

Thanks for the help

4 Replies

  • Persistence is specific to the pool. If the two pools you want to use have different members, then you would want to specify a different persistence cookie name depending on which pool to send the client to. So you could use 'persist cookie insert pool1_cookie 0' to insert a session cookie for pool 1 / use the existing cookie in the client's request to select the same pool1 member.

     

     

    Here is some pseudo code to start with:

     

     

      
      when HTTP_REQUEST {  
      
          Check if client has pool1 persistence cookie  
         if {[string length [HTTP::cookie value $pool1_persist_cookie_name]]}{  
      
             Client has pool1 persistence cookie.  Check if pool is up?  
      
             Specify pool1 persistence to select same pool1 member  
            persist cookie insert $pool1_persist_cookie_name 0  
      
          Check if client has pool2 persistence cookie  
         } elseif {[string length [HTTP::cookie value $pool2_persist_cookie_name]]}{  
      
             Client has pool2 persistence cookie.  Check if pool is up?  
      
             Specify pool2 persistence to select same pool2 member  
            persist cookie insert $pool2_persist_cookie_name 0  
      
         } else {  
      
             Client has no persistence cookie, so select between pool1 and pool2  
      
                Set persistence based on selected pool  
      
         }  
      }  
     

     

     

    Aaron
  • So to clarify, can the rule be simplified even further?

    I already have a persistence profile set for HTTP Cookie Insert with cookie name set to "FOO"

    My understanding of this named cookie is that if the user has no cookie set (first entry) then the irule will pool that user to one of the pool's and that user will have a persistence record set for that pool...that is until the irule chooses a different pool (killing the persistence cookie) or the member gets marked down (also killing the persistence cookie)

    So with a named cookie each unique user session can have only a single instance of the persistence cookie...either pointing at pool1 or pool2.

    Joe could have FOO persistence cookie pointing his requests at pool1/member4, while at same time Paul could have FOO persistence cookie pointing his requests at pool2/member1.

    Each time a user changes pools via iRule pool command then a fresh member is selected and the user is then persisted there. Is all that correct?

    I would like to rely on the persistence profile in the VS to set the cookie and then just look for the presence of that cookie by name in the irule. If its not there, then I know its a new connection and I can select any pool for them. If it is there, I just want to send them along to that same pool and member referenced by the cookie and terminate irule processing.

    My assumption is that if the persistence profile is activley inserting a cookie, then in the iRule I can just persist passivley on that cookie name just like if a webserver had inserted it. Correct?

       
        
     when RULE_INIT {   
     set ::cnt 0   
     }   
     when HTTP_REQUEST {     
         if {[HTTP::cookie exists FOO]}{     
             persist cookie passive FOO   
                 This should pass connection along to the   
                 pool/member that the client has in the    
                 persistence record...irule terminates here   
                 just like I did a 'pool' command...correct?   
         } else {   
             incr $cnt   
             if { $cnt = 4000 } {    
                  set ::cnt 0   
                  pool pool2 New FOO cookie for user inserted via profile 
             } else {    
                  pool $pool1 New FOO cookie for user inserted via profile   
             }    
         }     
     }   
        
     

    Thanks for the help and sorry if I am missing a point somewhere
  • There can only be one default pool associated with a virtual server. This default pool would be used if the rule didn't specify a new pool. The persistence cookie has an encoding of the pool member IP:port. So consider the following scenario:

     

     

    1. a client is selectively load balanced to pool2 member 1.1.1.1:80 by an iRule

     

    2. client receives a persistence cookie from the persistence profile for 1.1.1.1:80

     

    3. client makes a new request to the virtual server with the persistence cookie for 1.1.1.1:80

     

    4. if the iRule doesn't select pool2, LTM would not know to automatically select pool2 and pick the original member

     

     

    You can test this to confirm.

     

     

    If you can guarantee pool1 and pool2 would never have a pool member in common, I suppose you could decode the IP:port from the cookie, check to see if the IP:port is a member of pool2 and then use pool2. But I think it would be much easier to use a separately named persistence cookie for each pool and select the pool based on the presence of the persistence cookies.

     

     

    Aaron

     

  • Ok, so you are saying that in the above:

     

      
     persist cookie passive FOO  
     

     

    Is not enough to actually cause the VS to hand the connect to the last pool/member as only the member and port are in the persistence record?

     

    In you earlier post with pseudo code you wrote above,

     

     

     
     persist cookie insert $pool1_persist_cookie_name 0 
     

     

     

    I only saw the 'persist' and did not see a subsequent 'pool' command. Is that possible only because in your example 2 separate cookies are used per pool, but in my example of one cookie this functionality is not possible and another 'pool' command is needed after the persist?

     

    If we do remove the cookie name from the persistence profile, my understanding is that 9.x LTM will use auto-generated per pool cookie names that are "BigIP" so we will end up with a cookie per pool...

     

    Does that somehow allow for bypassing issuing the pool command after the persist command as in your example?

     

    Thanks for your patience : )