Forum Discussion

bob_rao_7722's avatar
bob_rao_7722
Historic F5 Account
Mar 14, 2006

iRule that will limit connections

I am trying to write an irule that will do the following:

 

1) limit the web servers to 50 connections each.

 

2) any connection after 50 will be redirected to another site.

 

3) Clients are using cookies for persistence.

 

4) Once a client gets a cookie we need to keep persistence.

 

rule session_limit {

 

 

my qustion is - i

 

1)Is the max_active_clients- of 50, is that for the pool or each member?

 

2) How do we guarantee that we always send users to a server that has the capacity? We notice - that when we have a few connections available on a server. We will still get redirected – for example - one servers will have 40 connections- the other about 10. So we will get redirted - in this case to yahoo. Is there a way to set the limit on the per node basis? It looks like we are setting the limit on the per vip basis.

 

 

Below is what we have:

 

 

rule session_limit {

 

 

when RULE_INIT {

 

 

array set ::active_sessions { }

 

 

set ::total_active_clients 0

 

 

set ::max_active_clients 50

 

 

}

 

 

when HTTP_REQUEST {

 

 

if { [HTTP::cookie exist "BIGipServerhalifax"] } {

 

 

pool halifax

 

 

incr ::total_active_clients

 

 

log "Total Clients $::total_active_clients"

 

 

log "Active Sessions $::active_sessions { } "

 

 

} else { if { $::total_active_clients < $::max_active_clients } {

 

 

if { [HTTP::uri] contains "linkID=halifax" } {

 

 

pool halifax

 

 

incr ::total_active_clients

 

 

} else { HTTP::redirect "http://pleasehold.evenue.net/bigip/nocookies.html" }

 

 

} else { HTTP::redirect "http://www.yahoo.com/"

 

 

return

 

 

}

 

 

}

 

 

}

 

 

when CLIENT_CLOSED {

 

 

 

 

incr ::total_active_clients -1

 

 

}

 

 

}

 

 

 

  • Deb_Allen_18's avatar
    Deb_Allen_18
    Historic F5 Account
    Hey Bob --

     

     

    The rule you've created will actually enforce a connection limit at the rule/virtual server level, not for each pool member. You could set connection limits on each node as required, and use "observed" or "least connections" lb method to ensure that all servers are utilized up to the max of the VS limit without the skewing you're seeing.

     

     

    And unless I'm reading your code wrong, it looks like you may want to reverse the comparison of total to max? Looks like you're redirecting only if total < max?

     

     

    And finally, in case the rule might be applied to more than 1 VS, you should be aware that since the rule uses global array values for the counter, that array value would be shared across multiple instances of the same rule.

     

     

    HTH

     

    /deb
  • bob_rao_7722's avatar
    bob_rao_7722
    Historic F5 Account
    Is the connections based on active connections or total connections?

     

    When we look at the node - we see 0 active connections, and we see 200 plus "tot" connections. It is enforcing the connection limit on "tot".

     

    We set a limit on the node level for 25 connections each, and we have a 50 connection limit on the VS level with the iRule.

     

    Once we hit the max on the "tot" connections, we can not initiate new connection to the VIP, we are redirected to yahoo.

     

    So what we are trying to do- is set a limit to 50 active sessions - 25 active sessions on each server.

     

    What should I edit to accomplish this?

     

     

    thanks

     

    Bob

     

     

  • Deb_Allen_18's avatar
    Deb_Allen_18
    Historic F5 Account
    Make sure I have the logic straight first:

    
      if cookie exists
          load balance to default pool w/persistence
          (session already exists, so don't increment counter)
      if no cookie exists
          if uristring exists
            redirect to "nocookies" page
          if connection limit not yet reached
            load balance to default pool
            increment counter
          else if connection limit already reached
            redirect to "server busy" page

    By re-ordering your original conditions a bit, eliminating one unused array, and incrementing a bit differently, we get:

    
    rule session_limit {
    when RULE_INIT {
      set ::total_active_clients 0
      set ::max_active_clients 50
    }
    when HTTP_REQUEST {
    ; If persistence cookie already exists,
    ; allow persistent connection without incrementing counter
      if { [HTTP::cookie exists "BIGipServerhalifax"] } {
          pool halifax
          return
    ; If no cookie, check for URI link parameter
    ; & redirect if present
      } else {
        if { [HTTP::uri] contains "linkID=halifax" } {
          HTTP::redirect "http://pleasehold.evenue.net/bigip/nocookies.html" 
          return
        }
    ; Still no cookie
    ; Check limit vs. active
    ; Allow in if there's room, and incr counter for this new cnx
        if { $::total_active_clients < $::max_active_clients } {
          incr ::total_active_clients
          pool halifax
          return
    ; otherwise redirect
        } else {
          HTTP::redirect "http://www.yahoo.com/"
          return
        }
      }
    }
    when CLIENT_CLOSED {
      incr ::total_active_clients -1
    }
    }

    This will enforce a connection limit of 50 total concurrent users on the VS. If you use "least connections" load balancing, you will get the most even distribution of connections across the server pool. I'm not sure how nicely node connection limits will play with the rule limits, so I'm going to recommend you leave off the node limits until you have the rule logic working the way you want, and then I'll leave the question of node limits open for your experimentation.

    HTH

    /d
  • Hi

     

     

    I am trying to implement a very similar setup, I was finding that the client_close was triggering for both active clients and those being redirected, so I put a HTTP::close and a TCP::close after the redirect with an increment of the current active users thus triggering the client close and decrementing it again, this seemed to solve that issue.

     

     

    My current problem is that client browser triggers the client_close after a period of inactivity (it seems to happen at different times for different browsers) at this point the number of active users gets decremented allowing a new user in, but the session cookie for the first user is still present so they can still gain access also, thus bursting the caps.

     

     

    Any pointers anyone could give me with this would be gratefully received. See my irule below.

     

     

    Thanks

     

     

    David

     

     

    when RULE_INIT {

     

    set ::total_active_clients 0

     

    set ::max_active_clients 1

     

    log local0. "rule session_limit initialized: total/max: $::total_active_clients/$::max_active_clients"

     

    }

     

    when CLIENT_ACCEPTED {

     

    log local0. "Client accepted"

     

    log local0. "active clients $::total_active_clients"

     

    }

     

    when HTTP_REQUEST {

     

    log local0. "current active clients $::total_active_clients"

     

    ; test cookie presence

     

    if {[HTTP::cookie exists "ClientID"]} {

     

    log local0. "active user with cookie making http request"

     

    set need_cookie 0

     

    set client_id [HTTP::cookie "ClientID"]

     

    ; if cookie not present & connection limit not reached, set up client_id

     

    } else {

     

    if {$::total_active_clients < $::max_active_clients} {

     

    log local0. "http request from new client access granted. cookie set."

     

    set need_cookie 1

     

    set client_id [format "%08d" [expr { int(100000000 * rand()) }]]

     

    log local0. "current active clients $::total_active_clients"

     

    log local0. "new active client"

     

    incr ::total_active_clients

     

    log local0. "current active clients $::total_active_clients"

     

    ; otherwise redirect

     

    } else {

     

    log local0. "http request from non active connection denied"

     

    HTTP::redirect "http://www.google.com"

     

    incr ::total_active_clients

     

    log local0. "attempting to close connection"

     

    catch HTTP::close

     

    catch TCP::close

     

    return

     

    }

     

    }

     

    }

     

    when HTTP_RESPONSE {

     

    ; insert cookie if needed

     

    if {$need_cookie == 1} {

     

    HTTP::cookie insert name "ClientID" value $client_id

     

    }

     

    }

     

    when CLIENT_CLOSED {

     

    ; decrement current connection counter for this client_id

     

    log local0. "current active clients $::total_active_clients"

     

    log local0. "client closed"

     

    log local0. [IP::remote_addr]

     

    if {$::total_active_clients > 0} {

     

    log local0. "decremeting active clients"

     

    incr ::total_active_clients -1

     

    }

     

    log local0. "current active clients

     

    $::total_active_clients"

     

    }

     

  • I am testing your rule, and sometimes I get the following

     

    Sep 11 10:09:12 tmm tmm[1055]: 01220001:3: TCL error: Rule rule_http-session-limit - Operation not supported. Multiple redirect/respond invocations not allowed (line 23) invoked from within "HTTP::redirect "http://www.google.com""

     

     

     

    sort of confusing, as line 23 is this log statement

     

    log local0. "current active clients $::total_active_clients"

     

     

     

    Thoughts?

     

    -L