Load balancing based on ASP SessionID

Problem this snippet solves:

The code separates into 2 irules, one for request and one for response. The app in question only issues out 1 cookie. The al_start.asp? starts the session adn teh session will end with al_stop.asp or with a timeout so this what the irules rotate around

Code :

#request irule

when RULE_INIT { 
        #initialize the arrays the first time the irule is called 
        array set ::sessiontrackingarray {} 
        array unset ::sessiontrackingarray 
    array set ::sessionlbarray {} 
        array unset ::sessionlbarray 
}   
 when HTTP_REQUEST { 
    set debug 0 
        #scan http header for asp session cookies if the cookie exists set sessionid to the cookie value 
        set sessioncookie [findstr [HTTP::cookie names] "ASPSESSION" 0 20] 
    set sessionid [HTTP::cookie $sessioncookie] 
        #set the time to current, set the idle time to current -121 seconds. 
    set currtime [clock seconds] 
    set expiredtime [expr {$currtime} - 121] 
    set poolname nameofpool 
    set server1lb 0 
    set server1ip "x.x.x.x"  #ip address omitted this would be the ip address of the first pool member
    set server2lb 0 
    set server2ip "x.x.x.x"  #ip address omitted this would be the ip address of the second pool member
    set server3lb 0 
    set server3ip "x.x.x.x"  #ip address omitted this would be the ip address of the third pool member
    set server4lb 0 
    set server4ip "x.x.x.x"  #ip address omitted this would be the ip address of the fourth pool member 
        # Search for ASP Session Cookie 
    if { not ([HTTP::cookie exists "$sessioncookie"])} { 
                # If request is not "al_start.asp?", exit iRule and follow default pool and LB Method 
        if { not ([HTTP::uri] contains "al_start.asp?") } { 
                  return 
                } 
        else { 
                # if there are no values in the sessionlbarray - i.e al_start.asp? seen, exit irule and just use the lb method for the pool 
        #  if {not [array names ::sessionlbarray]} { 
                #                pool $poolname 
        #        return 
                #        } 
        #    else { 
                                # Scan array and delete old/hung sessions.  Any session that has a timestamp in the sessiontracking array older than the $expiredtime variable will be deleted 
                                # from both the session tracking array and lbtracking array so that it is not considered when making the lb decision 
                foreach sesskey [array names ::sessiontrackingarray] { 
                    set sessiontime $::sessiontrackingarray($sesskey) 
                   if { $debug }{ log local0.info "for session $sesskey sessiontime is $sessiontime and expiredtime is $expiredtime" }
                                        if { $sessiontime < $expiredtime } {   
                                       if { $debug }{   log local0.info "session last touched time of $sessiontime for session $sessionid is over 121 seconds old. removing session from tracking arrays" }
                        unset ::sessiontrackingarray($sesskey) 
                        unset ::sessionlbarray($sesskey) 
                    } 
                } 
                                # Session on each server count 
                              if { $debug }{  log local0.info "array sessionlbarray [array size ::sessionlbarray]" }
                foreach lbentry [array names ::sessionlbarray] { 
                                        if { $debug }{log local0.info "lbentry is $lbentry sessionarraylb is $::sessionlbarray($lbentry)"} 
                    switch $::sessionlbarray($lbentry) { 
# masking ip addresses at customer request
                        "x.x.x.x" {set server1lb [expr {$server1lb} + 1]} 
                        "y.y.y.y" {set server2lb [expr {$server2lb} + 1]} 
                        "z.z.z.z" {set server3lb [expr {$server3lb} + 1]} 
                        "w.w.w.w" {set server4lb [expr {$server4lb} + 1]} 
                    } 
                                } 
                                # Set Count Array to hold session count and server IP. 
                                
                                set counterarray($server1ip)  $server1lb 
                                set counterarray($server2ip)  $server2lb 
                                set counterarray($server3ip)  $server3lb 
                                set counterarray($server4ip)  $server4lb 
                                if { $debug }{  log local0.info "server1count is $server1lb, server2count is $server2lb, server3count is $server3lb, server4count is $server4lb" }
                                #test the pool member status.  If a pool member is down, remove it from the temporary array counterarray so that is 
                                #is not considered when making the lb decision 
                                foreach membercheck [array names counterarray] { 
                                        if { $debug }{log local0.info "membercheck is $membercheck, array element value is $counterarray($membercheck)"} 
                                        if { not ([LB::status pool $poolname member $membercheck 80] eq "up") }{ 
                                                if { $debug }{log local0.info "pool status is [LB::status pool $poolname member $membercheck 80]"} 
                                                  unset counterarray($membercheck) 
                                                if { $debug }{ log local0.info "removing server $membercheck from the counterarray"}   
                                                  } 
                                        }   
                                        set lbholder 1000000000 
                                        foreach lbcounter [ array names counterarray ] { 
                                                if { $lbholder > $counterarray($lbcounter) }{ 
                                                        set lbholder $counterarray($lbcounter) 
                                                        set ipholder $lbcounter 
                                                } 
                                        } 
                                # set the variable winner to the lowest value of the server session counters         
                        #        set winner [lindex [lsort -integer { array get counterarray }] 0] 
                                if { $debug }{ log local0.info " load balancing to $ipholder"} 
        #                        persist cookie insert cookie_cco 
                                if { $debug }{log local0.info "setting pool $poolname to lb to member $ipholder"} 
                                pool $poolname member $ipholder 80 
                                if { $debug }{ log local0.info "pool member $ipholder status is [LB::status]"} 
                                                return 
                                        } 
                #} 
        } 
        else { 
                pool $poolname 
                persist uie [HTTP::cookie "$sessioncookie"] 1200   
                # When cookie exists and it's NOT "AL_STOP.asp", reset session timestamp 
                if { not ([string tolower [HTTP::uri]] contains "al_stop.asp")} { 
                        set ::sessiontrackingarray($sessionid) $currtime 
                        if { $debug }{  log local0.info "new timestamp for session $sessionid is $::sessiontrackingarray($sessionid)" }
                } 
                else { 
                 if { $debug }{  log local0.info "al_stop seen.  removing $sessionid entries from both arrays" }
                unset ::sessiontrackingarray($sessionid) 
                unset ::sessionlbarray($sessionid) 
                } 
        } 
} 

#response irule

when HTTP_RESPONSE { 
        set debug 0 
        set currtime [clock seconds] 
        set sessioncookie [findstr [HTTP::cookie names] "ASPSESSION" 0 20] 
        set sessionid [HTTP::cookie $sessioncookie] 
        if { $debug } { log local0.info "sessionid is $sessionid"} 
        if { $debug }{ log local0.info "asp session cookie name is $sessioncookie " } 
        # test to see if the IIS server is setting a cookie 
    if { not [HTTP::header exists "Set-Cookie"] } {     
                if { $debug }{log local0.info "no set cookie in http response, exiting"} 
                return } 
    else { 
                        if { [HTTP::cookie exists "$sessioncookie"] } { 
                       persist add uie [HTTP::cookie "$sessioncookie"] 1200 
                } 
                #  add sessionid and time to the session time tracking array 
                set ::sessiontrackingarray($sessionid) $currtime 
                        if { $debug }{log local0.info "adding sessionid [HTTP::cookie "$sessioncookie"] to sessiontracking array with clock value $currtime"} 
                        # add sessionid and lb server to the array tracking sessions to server 
            set ::sessionlbarray($sessionid) [LB::server addr] 
                        if { $debug }{log local0.info "adding session [HTTP::cookie "$sessioncookie"] to array sessionlbarray with server value [LB::server addr]"} 
    } 

}
Published Mar 18, 2015
Version 1.0

Was this article helpful?

No CommentsBe the first to comment