Forum Discussion

El-Guapo_29797's avatar
El-Guapo_29797
Icon for Nimbostratus rankNimbostratus
Jun 30, 2014

How to load balance thick clients based on HTTP parameter?

I have a pool of 6 nodes & need an iRule to use with Universal which balances thick clients. Each client will have a unique string inserted in header. String starts with cid + numbers such as: http://xyzserver:8000/xxx/xxx.svc?cid=123-456-7895. Using Universal, how do I write this iRule?

 

8 Replies

  • shaggy's avatar
    shaggy
    Icon for Nimbostratus rankNimbostratus

    Universal persistence:

    http://support.f5.com/kb/en-us/solutions/public/7000/300/sol7392.html

    Your iRule would look something like:

    when HTTP_REQUEST { 
     set cid [findstr [HTTP::uri] "cid" 4 ";"] 
     if { $cid != "" } { 
     persist uie $cid 
     } 
    }
    

    The ";" value is the terminator signifying the end of the parameter value, so you will need to adjust as needed.

    You would create a universal persistence profile that references the iRule and assign it to the desired virtual server

  • Universal persistence:

    http://support.f5.com/kb/en-us/solutions/public/7000/300/sol7392.html

    Your iRule would look something like:

    when HTTP_REQUEST { 
     set cid [findstr [HTTP::uri] "cid" 4 ";"] 
     if { $cid != "" } { 
     persist uie $cid 
     } 
    }
    

    The ";" value is the terminator signifying the end of the parameter value, so you will need to adjust as needed.

    You would create a universal persistence profile that references the iRule and assign it to the desired virtual server

  • If I may add, findstr is one of those crazy cool unsung commands that a lot of people don't know about (even though they probably see it all the time). It's not a native TCL command, but rather a highly optimize iRule-specific command. The syntax is basically like this:

    findstr [source string] [find string] [skip-count] [terminator count or string]
    

    The [skip count] value is the number of characters to skip once you've found the string, so given the URI:

    http://xyzserver:8080/xxx/xxx.svc?cid=123-456-7895
    

    And the findstr command:

    log local0. [findstr [HTTP::uri] "?cid=" 5]
    

    It will find the part of the string that starts with "?cid="

    ?cid=123-456-7895
    

    And then skip 5 characters ahead

    123-456-7895
    

    The [terminator string or count] value basically tells you where to end. You can use a terminator count:

    set uri "http://xyzserver:8080/xxx/xxx.svc?cid=123-456-7895"
    log local0. [findstr $uri "?cid=" 5 5
    
    123-4
    

    You skip 5 characters (?cid=) and then grab the next 5. If you use a string terminator, then you're telling it to stop collecting when it gets to a specific string value. In the example above, Matin was terminating on the ";" semicolon. If none existed, then collection would continue to the end of the source string. One important note here, the skip count value is arbitrary, in which it won't skip any characters if it's not included, and you cannot have a terminator without a skip count.

    Also, would I have to use cookie or cookie always-send as persistence with this iRule?

    Now on to the second part. The fact that you're asking about cookie persistence leads me to assume that the cid value isn't always going to be in the URI. If that's true, and also assuming that the cid is at least in the FIRST request, then you need some other mechanism to maintain persistence after the first request. The easiest would probably be a cookie. So something like this:

    when HTTP_REQUEST { 
        set cid [findstr [HTTP::uri] "cid" 4 ";"] 
        if { $cid != "" } { 
            persist uie $cid
            set setcookie 1
        } elseif { [HTTP::cookie exists CID] } {
            persist uie [HTTP::cookie value CID]
        }
    }
    when HTTP_RESPONSE {
        if { [info exists setcookie] } {
            unset setcookie
            HTTP::cookie insert name CID value $cid
        }
    }
    
  • The answer basically depends on the client. HTTP is stateless, so every request MUST contain some unique piece of information that the server can use to derive persistence, session management, etc.

     

    So, if the client WILL ALWAYS add "?cid=" to its request URIs, then Shaggy's original iRule will do the trick.

     

    If, however, the client only sends that cid value once at the beginning of the session, then you need something else to use for ongoing persistence. The best choice, if the client supports it, is cookies, and that would be the last iRule above.

     

  • The findstr command allows either a terminator string or terminator count, so the following should work:

    findstr [HTTP::uri] "cid=" 4 32]
    
  • what is the semicolon do when I used cid" 4 ";" ??

    The syntax for findstr is:

    findstr [source string] [search string] [skip count] [terminator character or count]
    

    So:

    findstr [HTTP::uri] "cid=" 4 32
    

    says, find the part of the string that starts with "cid=" in the URI, skip 4 characters (the length of "cid="), and then move 32 characters up and stop. Now, if for example you had an X509::subject string:

    CN=bob, OU=lab, DC=DOMAIN, DC=COM
    

    And you wanted to grab the user's name, you'd use the character version of the terminator:

    findst [X509::subject [SSL::cert]] "CN=" 3 ","