Election Hash Load Balancing And Persistence

Problem this snippet solves:

Deterministically load balances and persists connections to a server using an election hash in lieu of maintaining a large persistence table in memory. Very efficient solution for load balancing high-volume caches & proxies where low overhead stickiness to the same server is desirable for matching requests. The election hash solution overcomes the shortcomings of typical hash algorithms which can disintegrate when pool membership is in flux. Be sure to read Nathan's comprehensive description of the problem and his simple and elegant solution here: http://devcentral.f5.com/Default.aspx?tabid=63&articleType=ArticleView&articleId=135

How to use this snippet:

Note: These iRules require LTM version 9.4.2 or better.

Code :

# iRule Source: Basic Election Hash iRule

#  Election Hash iRule
#  Compute Hash - MD5
# Version 3.0 Dec 4th 2007
#
#  MD5 calculation of Server + URI
#  Rule selects Server that scores highest
#
# S = Current high score
# N = Node being evaluated
# W = Winning node
#
# Change "myPool" to your pool name.
#
when HTTP_REQUEST {
  set S ""
  foreach N [active_members -list myPool] {
    if { [md5 $N[HTTP::uri]] > $S } {
      set S [md5 $N[HTTP::uri]]
      set W $N
    }
  }
  pool myPool member [lindex $W 0] [lindex $W 1]
}

# LTM sample log results with four nodes active in the pool:

Rule: Node: 172.29.4.53/32  Score: 917
Rule: Node: 172.29.4.54/32  Score: 67
Rule: Node: 172.29.4.55/32  Score: 74
Rule: Node: 172.29.4.56/32  Score: 577
Rule: Picked Node: 172.29.4.53  URI: /images/logo.gif  Highest Score: 917

# LTM sample log results with four nodes active in the pool:

Rule: Node: 172.29.4.53/32  Score: 917
Rule: Node: 172.29.4.54/32  Score: 67
Rule: Node: 172.29.4.55/32  Score: 74
Rule: Node: 172.29.4.56/32  Score: 577
Rule: Picked Node: 172.29.4.53  URI: /images/logo.gif  Highest Score: 917

# The results when node .53 is unavailable:

Rule: Node: 172.29.4.54/32  Score: 67
Rule: Node: 172.29.4.55/32  Score: 74
Rule: Node: 172.29.4.56/32  Score: 577
Rule: Picked Node: 172.29.4.56  URI: /images/logo.gif  Highest Score: 577

# The iRule correctly scored each possible node against the object requested and selected the highest scoring server. Removing a node only affected traffic which that node had previously won.

# iRule Source: Compound Election Hash iRule

# Election Hash iRule
# Compound Compute Hash - MD5
# Version 3.0 Dec 4th 2007
#
# Basic hash picks a pool containing
# a subset of servers. Then perform
# election hash across pool members.
# Pools must be named Pool_<0-n>. 
# Change % 10 to highest numbered pool.
#
# S = Current high score
# N = Node being evaluated
# W = Winning node
# P = Pool name
#
when HTTP_REQUEST timing on {
  set S ""
  binary scan [md5 [HTTP::uri]] i1 P
  set P Pool_[expr $P % 10]
  foreach N [active_members -list $P] {
    if { [md5 $N[HTTP::uri]] > $S } {
      set S [md5 $N[HTTP::uri]]
      set W $N
    }
  }
  pool $P member [lindex $W 0] [lindex $W 1]
}

# Note: For compatibility prior to v9.4.2 the following was created

#  Election Hash iRule
#  Compute Hash - MD5
#  Version 3.1 September 25th 2009
#
#  MD5 calculation of Server + URI
#  Rule selects Server that scores highest
#
# S = Current high score
# N = Node being evaluated
# W = Winning node
#
# Change "myPool" to your pool name.
# Replace IPADDR1, IPPADDR2, IPADDRN with the node IPs contained in "myPool"
# Replace  with the port number of the nodes contained within "myPool"
# 
when HTTP_REQUEST {
  set GOOD_NODES {}
  set NS {IPADDR1 IPADDR2 IPADDRN }
  set portnum 
  set S ""
  # This looks through myPool nodes to determine the one's that are active
  # and passes it onto the array called GOOD_NODES
  foreach N $NS {
        if { [LB::status pool myPool $N $portnum] eq "up" } {
           lappend GOOD_NODES $N
        }      
   }
   
  foreach N $GOOD_NODES {
    if { [md5 $N[HTTP::uri]] > $S } {
      set S [md5 $N[HTTP::uri]]
      set W $N
    }
  }
  pool myPool member [lindex $W 0] [lindex $W 1]
}

Tested this on version:

9.4
Published Mar 17, 2015
Version 1.0

Was this article helpful?

No CommentsBe the first to comment