Forum Discussion

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

maintain persistence (direct/redirect) using tag info

Good Afternoon,

 

 

I am a noob with iRules, so I appologize for asking a silly question, but here goes:

 

 

I have an application that is a conferencing app, and when a user connects to the application, any one of the servers can redirect to other servers for a specific conference id (the application dev team built in there own least conns mechanism within there app). Right now they use specific FQDN's to redirect to.

 

 

My task is to put some F5 6400's in, and use the least cons mechanism, then use the F5 to take header info sent to the client to direct the session to the correct server once the app does the backend thing. So each response from the individual servers will contain something like "serverID=0001" where 0001 is mapped to a specific pool member.

 

 

Here's what my noob brain picked out so far:

 

 

when HTTP_REQUEST {

 

if {[HTTP::uri] equals {cs.conferenceservers.com/}} {pool csmember1}

 

}

 

}

 

 

but I realize that this isn't right, I think I need something like a contains , or something like that within the URI

 

 

Any help would be greatly appreciated.

 

 

  • So here's an update:

     

     

    Here is my string to node IP mapping:

     

     

     

    cs-A010305 10.1.3.5

     

    ds-A010305 10.1.3.6

     

    ms-A010305 10.1.3.7

     

     

    cs-A010308 10.1.3.8

     

    ds-A010308 10.1.3.9

     

    ms-A010308 10.1.3.10

     

     

    cs-AC1E0080 10.1.3.2

     

    ds-AC1E0080 10.1.3.3

     

    ms-AC1E0080 10.1.3.4

     

     

     

     

    and here's the irule I came up with:

     

     

    when http_request {

     

    if { [HTTP::uri] contains "cs-A010305"} {

     

    node 10.1.3.5 81

     

    }

     

    elseif { [HTTP::uri] contains "ds-A010305"} {

     

    node 10.1.3.6 81

     

    }

     

    elseif { [HTTP::uri] contains "ms-A010305"} {

     

    node 10.1.3.7 81

     

    }

     

    elseif { [HTTP::uri] contains "cs-A010308"} {

     

    node 10.1.3.8 81

     

    }

     

    elseif { [HTTP::uri] contains "ds-A010308"} {

     

    node 10.1.3.9 81

     

    }

     

    elseif { HTTP::uri] contains "ms-A010308"} {

     

    node 10.1.3.10 81

     

    }

     

    elseif { HTTP::uri] contains "cs-AC1E0080"} {

     

    node 10.1.3.2 81

     

    }

     

    elseif { HTTP::uri] contains "ds-AC1E0080"} {

     

    node 10.1.3.3 81

     

    }

     

    elseif { HTTP::uri] contains "ms-AC1E0080"} {

     

    node 10.1.3.4 81

     

    }

     

     

    when LB_FAILED {

     

    pool cs

     

    LB::reselect

     

    log "Selected server [LB::server] did not respond. Re-selecting node from cs."

     

     

     

    Does this look right? I am gonna give it a swing in the morning.

     

     

    Thanks,

     

     

    Cam

     

     

     

  • Colin_Walker_12's avatar
    Colin_Walker_12
    Historic F5 Account
    For that kind of list I'd either use a switch statement or a class. The switch statement is probably the fastest, but the class will be the simplest code, and easiest to update.

     

     

    First the switch:

     

     

     
     when HTTP_REQUEST { 
       switch -glob [string tolower [HTTP::uri]] { 
         "*cs-A010305*" { node 10.1.3.5 81 } 
         "*ds-A010305*" { node 10.1.3.6 81 } 
         "*ms-A010305*" { node 10.1.3.7 81 } 
         "*cs-A010308*" { node 10.1.3.8 81 } 
         "*ds-A010308*" { node 10.1.3.9 81 } 
         "*ms-A010308*" { node 10.1.3.10 81 } 
         "*cs-AC1E0080*" { node 10.1.3.2 81 } 
         "*ds-AC1E0080*" { node 10.1.3.3 81 } 
         "*ms-AC1E0080*" { node 10.1.3.4  81 } 
       } 
     } 
     

     

     

    That's going to be nice and fast, and a little easier to read/cleaner than the if/else chain. The easiest to maintain, though, is likely the class. For this you'd create a data group via the GUI or CLI of type "string" and enter in each mapping separated by a space, like so:

     

     

     
     class nodeMapping { 
       "cs-A010305 10.1.3.5" 
       "ds-A010305 10.1.3.6" 
       "ms-A010305 10.1.3.7" 
       "cs-A010308 10.1.3.8" 
       "ds-A010308 10.1.3.9" 
       "ms-A010308 10.1.3.10" 
       "cs-AC1E0080 10.1.3.2" 
       "ds-AC1E0080 10.1.3.3" 
       "ms-AC1E0080 10.1.3.4" 
     } 
     

     

     

    Then you'd use the findclass command in your iRule to use these key/value pairs, like so:

     

     

     
     when HTTP_REQUEST { 
       set nodeIP [findclass [string tolower [HTTP::uri]] $::nodeMapping " "] 
       if { [string length $nodeIP] > 0 } { 
         node $nodeIP 81 
       } 
     } 
     

     

     

    As you can see, this makes the actual iRule code much more condensed, and you can probably see how it will be easier to maintain, should the pairings change, or more be added. So the decision is yours where the tradeoff fits best for you.

     

     

    Colin
  • Colin,

     

    We've installed the rule, but it didn't seem to work. I've attached the entire config, so you can see how it's installed. Mapping_srvr1 is the original one, that does work, and Mapping_srvr2 is your version. Do you see any problems there at all syntax wise or anything? When we use srvr1, it works like a champ, but srvr2 version seems to just use least conns as we get different answers every time.
  • Thanks Colin! We'll give that one a shot. We noticed that too but didn't know enough about code to really figure it out.
  • Hi Collin,

     

     

    Does this rule inspect post data as well? Is there a different way to inspect post data?

     

     

    Thanks,

     

     

    Cameron