Forum Discussion

Gary_Bright_120's avatar
Gary_Bright_120
Icon for Nimbostratus rankNimbostratus
Mar 13, 2006

Persist iRule based on URI

Hi there I'm trying to write an iRule that will allow us Admins the choice of selecting a pool member and have persistence with that member.

At the moment we have a persistance profile or source_addr on the virtual server which holds for 15 minutes. This works great.

The pool is made up for 4 members

here is my first attempt


when HTTP_REQUEST {
if { [URI::decode [string tolower [HTTP::uri]]] contains "lbmember=3" } {
persist none
        pool pool_name member 1.1.1.1 80
persist source_addr 1800
}
}

Would someone be able to help me out with how I should go about setting this up.

To test I connect from my machine to the pool then view the persisent records in statistics find out which member I'm going to (not member 3) , then I refresh my page with lbmember=3 in the URL, but my persistence record still points to the old server and not 3

TIA

Gary

7 Replies

  • I think you probably want an else statement in there for the src_addr persist statement, otherwise, the persist none is reset to src_addr before the condition is completed.
  • Wouldn't you want it the other way around? If you find gb=3, persist none because there's only one server to send you to so you don't need to persist.

    Also, add some logging to make sure the logic is catching.

    
    when HTTP_REQUEST {
    if { [URI::decode [string tolower [HTTP::uri]]] contains "gb=" } {
    persist source_addr 1800
                    log "Persist"
    }
    if { [URI::decode [string tolower [HTTP::uri]]] contains "gb=3" } {
    use pool webpool member 1.1.1.3 80
                    persist none
    log "NO --  Persist"
    }
    }
    I think persistence takes precedence over selecting a pool member directly. Can anyone confirm that?
  • There are three member in the pool

    The logic for the iRule (in my mind (could be completely wrong)

    Was, iRule processes a request with gb= in the URI remove any persistence already setup, if any

    Then based on the number create a persistence rule with a particular webserver.

    As my persistence is set for 15mins I would have up until that time to forward any requests at the virtual server knowing that it will end up at my desired webserver until such time till my persistence timed out or I sent through another request with gb= in the URI.

    At the moment it does seem to process the iRule and for each request with gb=1 in the URI direct that request to member 1 but it doesn't setup the persistence.

    if I then make another request it will send to any member in the pool.

    
    when HTTP_REQUEST {
    if { [URI::decode [string tolower [HTTP::uri]]] contains "gb=" } {
    persist none
    log "Persist Turn Off"
    }
    if { [URI::decode [string tolower [HTTP::uri]]] contains "gb=3" } {
    use pool webpool member 1.1.1.3 80
    persist source_addr 1800
    log "Persist Setup to Member 3"
    }
    if { [URI::decode [string tolower [HTTP::uri]]] contains "gb=2" } {
    use pool webpool member 1.1.1.2 80
    persist source_addr 1800
    log "Persist Setup to Member 2"
    }
    if { [URI::decode [string tolower [HTTP::uri]]] contains "gb=1" } {
    use pool webpool member 1.1.1.1 80
    persist source_addr 1800
    log "Persist Setup to Member 1"
    }
    }
  • Deb_Allen_18's avatar
    Deb_Allen_18
    Historic F5 Account
    Since you are trying to insert a persistence record, rather than use an existing one, I think you need to use "persist add", and place the command AFTER the load balancing decision, so it can add the results of the load balancing decision to the persistence table:

    
    if { [URI::decode [string tolower [HTTP::uri]]] contains "gb=3" } {
      pool webpool member 1.1.1.3 80
      persist add source_addr 1800
      log "Persist Setup to Member 3"
    }

    (also, FYI: "use pool X" is legacy v4 syntax which at some point will be deprecated. For forward compatibility, use instead "pool X")

    HTH

    /d
  • Thanks for all your replys

    I did some more testing today and have come up with some interesting finds

    rather then specify a member in a pool I created 4 new pools each with one member and then rewrote the iRule to look like this

    
    when HTTP_REQUEST {
    if { [URI::decode [string tolower [HTTP::uri]]] contains "gb=" } {
    persist none
    log "Persist Turn Off"
    }
    if { [URI::decode [string tolower [HTTP::uri]]] contains "gb=4" } {
     pool member_www_04 member 4.4.4.4 80
    pool member_www_04
    persist source_addr 1800
    log "Persist Setup to Member 4"
    }
    if { [URI::decode [string tolower [HTTP::uri]]] contains "gb=3" } {
     pool member_www_03 member 3.3.3.3 80
    pool member_www_03
    persist source_addr 1800
    log "Persist Setup to Member 3"
    }
    if { [URI::decode [string tolower [HTTP::uri]]] contains "gb=2" } {
     pool member_www_02 member 2.2.2.2 80
    pool member_www_02
    persist source_addr 1800
    log "Persist Setup to Member 2"
    }
    if { [URI::decode [string tolower [HTTP::uri]]] contains "gb=1" } {
     pool member_www_01 member 1.1.1.1 80
    pool member_www_01
    persist source_addr 1800
    log "Persist Setup to Member 1"
    }
    }

    This worked first time, using the Statistics page to view persistence records I saw them update and I then had my persistence to my specific webserver.

    As soon as I change the line to specify a member in the pool (even thought there is only one) it stopped working.

    Nothing in the logs,

    Do you think this could be a bug?

    TIA

    Gary
  • unRuleY_95363's avatar
    unRuleY_95363
    Historic F5 Account
    Oh, yep. That is a bug. Using direct pool member selection doesn't cause a persistence record to be created (or a persist cookie to be inserted). You can add the persist record in an LB_SELECTED event like so (I've also made a few other optimizations):
    when HTTP_REQUEST {
       switch -glob [URI::decode [string tolower [HTTP::uri]]] {
       *gb=1* {
             pool webpool member 1.1.1.1 80
             set need_add_persist 1
          }
       *gb=2* {
             pool webpool member 2.2.2.2 80
             set need_add_persist 1
          }
       *gb=3* {
             pool webpool member 3.3.3.3 80
             set need_add_persist 1
          }
       *gb=4* {
             pool webpool member 4.4.4.4 80
             set need_add_persist 1
          }
       *gb=* {
             persist none
             log "Persist Turn Off"
          }
       }
    }
    when LB_SELECTED {
       if {[info exists need_add_persist]} {
          persist add source_addr [IP::client_addr] 1800
          unset need_add_persist
       }
    }