Forum Discussion

chris_connell_1's avatar
chris_connell_1
Icon for Nimbostratus rankNimbostratus
Oct 05, 2009

Testing 50 servers

 

Hi,

 

 

We have 50 servers to test and send traffic through, the probe which simulates a client generates a stream of traffic every half an hour.

 

 

The problem is that we have source persistency enabled which is required for our application, and during the tests, the probe is the only client that generates traffic.

 

 

This means with either round robin or leastconns our traffic only goes to one server, but we need to send traffic through all servers to make sure they are all working.

 

 

I was wandering if there are any options I could use to somehow send traffic to a different node each time, perhaps if the probe generated a request to a certain ip/url something could trigger the irule to send it to another node in turn.

 

 

The only crude way I can think of is enabling a node in turn in the crontab each half an hour but im sure there is a better way

 

thanks

 

  • I am afraid that you are going to need to get more alias addresses for your probe. That is truly the only way to not only test the app but how the load balancer reacts to it otherwise you testing won't pay a more accurate picture.

     

     

    CB

     

     

  • thanks, out of interest can you use irules to send to specific nodes as opposed to pools?

     

  • Hi

     

    yes you can do this

     

     

    Just search the site for node address port or pool member address port

     

     

    I hope this helps

     

     

    cb
  • hoolio's avatar
    hoolio
    Icon for Cirrostratus rankCirrostratus
    Here's an example from hwidjaja which uses persistence to ensure the specific pool member is selected based on an initial request with a query string parameter indicating the node that should be used. Subsequent requests are persisted to that same pool member based on the source IP address.

    iRule to Select alternate pool member based on QUERY_STRING

    http://devcentral.f5.com/Default.aspx?tabid=53&forumid=5&tpage=1&view=topic&postid=29295

    You could modify it slightly to take advantage of the URI::query command to parse the query string parameter value:

     
     when HTTP_REQUEST { 
      
        set time_out 3600 
      
         Check query string for node parameter.  Expect a two digit number indicating the pool member 
        switch [URI::query [HTTP::uri] "node"] { 
           01 { set selected_node 192.168.49.97 } 
           02 { set selected_node 192.168.49.98 } 
           03 { set selected_node 192.168.49.99 } 
           default { 
               No node parameter in query string, so check if there  
                 is an existing session table entry for this client IP 
              set selected_node [session lookup source_addr [IP::client_addr]] 
           } 
        } 
      
         Check if there was a matched node 
        if {$selected_node eq ""} { 
      
            No match, so use the default pool 
           pool [LB::server pool] 
      
        } else { 
      
            Found a match, so use that 
           pool [LB::server pool] member $selected_node 
      
            Add a session table entry based on the client IP, selected node address and the record timeout 
           session add source_addr [IP::client_addr] $selected_node $time_out 
        } 
     } 
     

    Aaron
  • I actually wrote an iRule for this exact purpose. You have to make sure and have DNS working properly. This article in support will help with that: https://support.f5.com/kb/en-us/solutions/public/5000/200/sol5299.html.

    Basically my rule uses DNS to process a URI for the string "server=server1.domain.com" and then takes the server name and does a DNS lookup and then connects to that single node. If "server=" is not in the URI string then it just moves on to whatever rule or pool you have balancing your normal traffic. This way you can monitor every server individualy for application functionality. The rule is below:

     
     when CLIENT_ACCEPTED { 
     set debug 1 
     set servername "localhost"  
     } 
      
     when HTTP_REQUEST { 
     set uri [string tolower [HTTP::uri] ] 
     if { $uri contains "server=" } { 
     set servername [findstr $uri "server=" 7 "&"] 
     if {$servername != "localhost"} { 
     HTTP::collect 
     NAME::lookup $servername 
     } else { 
     } 
     } 
     } 
      
     when NAME_RESOLVED { 
     set serverip [NAME::response] 
     if {$debug ==1 } { 
     log local0. "$servername IP address is $serverip"} 
     if {$servername != "localhost" } { 
     if { [catch {node $serverip [TCP::local_port] } ] } { 
     persist source_addr 60 
     log local0. "ERROR: attempting to assign to node $servername: $serverip" 
     } 
     } 
     HTTP::release 
     } 
     
  • Hi David,

     

    Very cool. I just wanted to add that we did something like this also, however, the con is if the DNS system slows down in response, it skews the performance so always make sure the DNS is healthy and responsive.

     

     

    CB
  • That was why i have it verify for the "server=" before doing the DNS lookup. That way if the string isn't present then the DNS hit isn't taken. I would only use this for monitoring application functionality on specific servers. But as you said I would watch it for a while to make sure you aren't impacting response times and i wouldn't rely on the response times with monitoring, only functionality.
  • hoolio's avatar
    hoolio
    Icon for Cirrostratus rankCirrostratus
    Nice idea. You could use [URI::query [HTTP::uri] server] to get the server parameter value. Also, you might want to check if the value is null before doing a DNS lookup:

     

     

    if {$servername != "localhost" && $servername != ""}{

     

     

    Aaron