ratio load balancing using rand function
Problem this snippet solves:
Summary: Use a pseudo random number to set a ratio for any iRule logic. This avoids using a global counter mechanism to track past selections.
iRule Methodology:
This iRule uses the rand function of expr to generate a pseudo random number and effectively generate a ratio for any iRule logic. The first example below sends 2% of connections to a separate pool. The remaining 98% of connections are sent to the virtual server's default pool. The second example selects a separate pool for 2% of requests to a specific set of URIs.
The original idea was from Jarvil in this forum post.
rand() man page section from the expr TCL wiki page:
Code :
http://www.tcl.tk/man/tcl8.4/TclCmd/expr.htm#M38 rand() Returns a pseudo-random floating-point value in the range (0,1). The generator algorithm is a simple linear congruential generator that is not cryptographically secure. Each result from rand completely determines all future results from subsequent calls to rand, so rand should not be used to generate a sequence of secrets, such as one-time passwords. The seed of the generator is initialized from the internal clock of the machine or may be set with the srand function. # Example 1 - Send 2% of connections to a different pool than the virtual server's default pool when CLIENT_ACCEPTED { # Send 2% of connections to a separate pool if { rand() < 0.02 } { pool other_pool } } # Example 2 - Send 2% of requests to a specific URI to a different pool than the primary pool when HTTP_REQUEST { # Check for a specific URI or set of URIs switch -glob [HTTP::uri] { "/uri1*" - "/uri2*" - "/uri3*" { # Send 2% of connections to a separate pool if { rand() < 0.02 } { pool other_pool # Exit from this event in this iRule return } } } # If we're still executing in this iRule, select the primary pool pool primary_pool } # Example 3 - Send 90% of requests to poolA, 5% to poolB and 5% to poolC. Use a session cookie to persist clients to the same pool over their HTTP session when HTTP_REQUEST { # Check if there is a pool selector cookie in the request # Use a switch statement to ensure only valid pool names are present # instead of accepting any pool name from the user supplied cookie switch [HTTP::cookie pool_cookie] { poolA - poolB - poolC { # Select the pool from the cookie pool [HTTP::cookie pool_cookie] set selected "" } default { # No pool selector cookie, so randomaly choose a pool # Save a random number between 0 and 1 set rand [expr { rand() }] if { $rand < .90 } { pool poolA set selected poolA } elseif { $rand < .95 }{ pool poolB set selected poolB } else { pool poolC set selected poolC } } } } when HTTP_RESPONSE { # Set a pool selector cookie if a pool was selected for this request if {$selected ne ""}{ HTTP::cookie insert name pool_cookie value $selected path "/" } }
- guicaotico_3425Nimbostratus
Hi hoolio, thank you for sharing your knowledge with us.
- Roberto_MendoncNimbostratus
Hey guys!
I'm trying to use the code described, I have a situation similar to the one explained in option 2.
But I'm getting the error 'error: [undefined procedure: rand()][rand()]'
BigIP version "BIG-IP 15.1.3 Build 0.38.11"