Forum Discussion

roykidder's avatar
roykidder
Icon for Nimbostratus rankNimbostratus
Aug 05, 2016

Respond with 5xx message when pool members connection limits reached (iRule?)

I have a use case where I have a pool of web server appliances that, when over loaded, simply time out. I want to set a connection limit on a per-member basis and then be able to hand back a 5xx to the client in the event that all pool members are overloaded. I'm assuming it would require an iRule but I'm not able to figure out how to do it. Since the pool members aren't actually down (they're marked unavailable when they reach their connection limit), testing for

 

if {[active_members [LB::server pool]] == 0}

 

didn't appear to work as I'd hoped. Likewise, the solution here didn't work either, even when I prepended the variable names with "static::" as suggested.

 

I'm currently running 11.6.0 code. Anyone have any suggestions?

 

3 Replies

  • Have you tried using "Fallback Host" within the HTTP profile ? When a connection limit is reached, this will come into play.

    You can also try LB_FAILED event:

    when LB_FAILED {
    
    }
    
  • Hi Roy,

    if the connection limit of a pool member has been exhausted, the pool member will become temporary marked down, so that it does not receive any new connections attemps. During this time

    [active_members]
    do not count nor list the pool member which connection limit is exhausted.

    You may try the iRule below. It performs a transparent

    LB::reselect
    in the case a pool member has just become unresponsive (but still marked as online) and also displays a
    [HTTP::response 503]
    in the case, that all remaining pool members are offline (or having their connection limits exhausted).

    when LB_FAILED {
        if { not [info exists "reselect_count"] } then {
            set reselect_count 0
        }
        if { [active_members [LB::server pool]] > $reselect_count } then {
            LB::mode rr
            LB::reselect
            incr reselect_count
        } else {
            HTTP::respond 503 content "The application is too busy to serve your requests..."
            set reselect_count 0
        }
    }
    

    Cheers, Kai

  • Changed the iRule to be v11-compliant

    when RULE_INIT {
            Set a global max for number of concurrent TCP connections
        set static::max_connections 2
         Set an HTML response to sent to clients who make a request while the VIP is over the max      connection count
        set static::html_content "over limit"
    
         Print debug messages to /var/log/ltm?  1=yes, 0=no
        set static::debug 1
    
         Initialize a counter for active connections (don't modify this)
        set static::active_connections 0
        }
        when HTTP_REQUEST {
    
         If we're over the limit for this connection, send a response
        if {$static::active_connections > $static::max_connections}{
    
         Send a response
        HTTP::respond 200 content $static::html_content
    
         Close the connection
        TCP::close
    
         Log a message to /var/log/ltm if debug is enabled
        if {$static::debug}{log local0. "Over limit (current/max:               $static::active_connections/$static::max_connections). Sent response to [IP::client_addr]"}
    
         We're not over the limit, so check if this is the first HTTP request on the TCP connection.  
        } elseif {[HTTP::request_num] == 1}{
          set validrequest 1
           Increment the TCP connection count.
          incr static::active_connections 1
        }
     }
    
    when CLIENT_CLOSED {
        A connection was closed, so decrement the global counter
       if {$validrequest == 1}{
           incr static::active_connections -1
       }
    }