Forum Discussion

papalukg_33581's avatar
papalukg_33581
Icon for Nimbostratus rankNimbostratus
Jul 17, 2008

Hashing load balancing and persistence

Hi all,

 

 

In our case we have a server pool and our main goal is that the traffic generated by the same clients must be always assigned to the same pool members. For this reason, we have implemented hash load balancing over the members of this pool. However, we need to hold a persistence table. The reason for the persistence table is that when a pool member goes down and its traffic is reassigned to another node the traffic should continue to pass through this node even if the faulty node comes up. This way the loss from "switching" traffic can be minimum.

 

 

Up to now we have implemented the example from hhttp://devcentral.f5.com/Default.aspx?tabid=63&PageID=151&ArticleID=135&articleType=ArticleView . The differences are that we use the event CLIENT_ACCEPTED and instead of HTTP::uri, we use IP::client_addr. Our problem is that we cannot add at the same time, entries to the persistence table according to the selection algorithm. Can anyone offer some help or suggest a different way?

 

 

  • The following is something I quickly wrote for a developer who wanted something simiiliar in that he wanted to the traffic to continue w/o having it "switch" when the faulty node came back up. This was written in v9.3.1 so I couldn't use the "active_members -list " command. This might exactly answer your question but it might help you think of solving your problem in a different way.

     
      This iRULE requires each pool have 1 member, and the last pool has all the combined members and it is equally balanced or prioritized. 
      The goal is when a client enters http://your.domain.com/?sid=P01 it will be directed to a specific pool.   
      If there is no URI, then look for a user-name in the http-header that that information and use CRC32 and create HASH number.   
      That number will be used to direct clients to a specific pool.  If there is no URI or user-name then do standard load balancing. 
      
     when HTTP_REQUEST { 
      This IF statement queries the URI to look for PO after a ? 
     if { [HTTP::query] contains "P0" } {  
      
      Takes the URI after ? skips 5 characters and sends the rest of the string to a variable. 
      For example, URI = /?sid=P01.  Looks at everything after ?, skips sid=P, scans the next 2 charcters/numbers  
      and sends the characters to the variable serverid. 
     set serverid [substr [HTTP::query] 5 2] 
      
      If another node is added to opentv, another pool statement must be added to the switch statement. 
     switch $serverid { 
     01 { pool pool_foobar.foo.com_01 } 
     02 { pool pool_foobar.foo.com_02 } 
     03 { pool pool_foobar.foo.com_03 } 
     04 { pool pool_foobar.foo.com_04 } 
     } 
     } 
     This statement checks to see if the is a user-name" 
     elseif { [HTTP::header exists "user-name"] } { 
      This creates a unique number using crc32 based on user-name in the http header and assigns it to a variable.  
      This unique number is passed to poolnum 
     set poolnum [crc32 [HTTP::header "user-name"]] 
      
      The following takes poolnum variable, divides it by 4 and assigns the remainder to poolnum.  
      This will result in the following answers 0,1,2,3.  If you divded by 5 then it's 0,1,2,3,4, etc,. 
      4 is equal to the total  of nodes in pool_foobar.foo.com_lb. 
      If a node is added then you must increment by N number of nodes that were added.   
      I.E., if 2 nodes are added then 4 + 2 = 6. 
     set poolnum [expr $poolnum % 4 ] 
      Increment the poolnum because we want a number higher then 0 to associate to a pool name. 
     incr poolnum 
      If another node is added to application, another pool statement must be added to the switch statement 
     switch $poolnum { 
     1 { pool pool_foobar.foo.com_01 } 
     2 { pool pool_foobar.foo.com_02 } 
     3 { pool pool_foobar.foo.com_03 } 
     4 { pool pool_foobar.foo.com_04 } 
          } 
     } 
     } 
      
      Triggered when the selected server fails in the selected pool, all connections on the failed node will be forced to reparticipate in load balancing. 
     when LB_FAILED {  
      if { [HTTP::header exists "user-name"] } { 
          set GOOD_NODES {} 
       When adding node then you must add the member node to NS 
          set NS {192.168.0.202 192.168.0.203 192.168.0.204 192.168.0.205} 
          foreach N $NS { 
             if { [LB::status pool pool_foobar.foo.com_lb member $N 8080] eq "up" } { 
                lappend GOOD_NODES $N 
             }       
          } 
        set NODENUM [crc32 [HTTP::header "user-name"]] 
        set NODENUM [expr $NODENUM % [active_members pool_foobar.foo.com_lb] ] 
        LB::reselect pool pool_foobar.foo.com_lb member [lindex $GOOD_NODES $NODENUM] 
        } 
        else {  
          pool pool_foobar.foo.com_lb 
          LB::reselect 
        } 
     } 
     

    I hope this helps

    CB