Forum Discussion

scottl_82413's avatar
scottl_82413
Icon for Nimbostratus rankNimbostratus
Feb 04, 2010

Redirect via Round Robin

Hello,

 

 

I'm not sure if an iRule is the best way to do this, or if the LTM can handle it in a better way.

 

 

We're going to publish a single URL - www.url.com, but need to redirect to www1.url.com, www2.url.com and www3.url.com. A simple round robin should be fine for determining when to redirect to which url.

 

 

Can an iRule handle this?

 

 

TIA.

6 Replies

  • Colin_Walker_12's avatar
    Colin_Walker_12
    Historic F5 Account
    First I'd ask, is there a reason you actually want to redirect to different host names, and not just different servers fed by a single host name? If you have www.url.com pointed to your VIP on your LTM and 3 servers in the pool that VIP feeds, you'd have RR load balancing taken care of already.

    Regardless, if you actually want to do redirects to those host names you could do something like:

      
      when CLIENT_ACCEPTED {  
        set c 0  
      }  
        
      when HTTP_REQUEST {   
        switch c {  
          0 {   
            HTTP::redirect "http://www1.url.com"  
            incr c  
          }  
          1 {  
            HTTP::redirect "http://www2.url.com"  
            incr c  
          }  
          2 {  
            HTTP::redirect "http://www3.url.com"  
            set c 0  
          }  
        }  
      }  
      

    That's a simple take on it without any error checking, but you get the idea. Hopefully it gets you started.

    Colin
  • Well, that didn't seem to work, and I'm having a harder time with this than I thought I would.

     

     

    We've also tried sending the client to www.url.com/a, www.url.com/b, www.url.com/c - again, with no success.

     

     

    Anyone have any ideas or know what I'm missing?

     

     

    Thanks again...
  • If I understand your question, you need each client to be redirected in turn? The CLIENT_ACCEPTED event would localize to a single client. For a much broader scope I think you'd need some state management, a global variable.

     

     

     
     when RULE_INIT {   
       set ::c 0   
       }   
     when HTTP_REQUEST { 
       event enable    
       switch $::c {   
         0 {    
           HTTP::redirect "http://www1.url.com"   
           incr ::c 
           event disable   
         }   
         1 {   
           HTTP::redirect "http://www2.url.com"   
           incr ::c 
           event disable   
         }   
         2 {   
           HTTP::redirect "http://www3.url.com"   
           set ::c 0 
           event disable   
         }   
       }   
     }  
     

     

     

    ** in testing the first version of this sample it occurred to me that the switch was firing for at least two conditions at a time (c = 0, then c = 1, etc.) - which makes sense considering my IE browser is opening two connections to the server simultaneously. So I added the event commands to shunt this behavior. You still probably want to first check for the [HTTP::host] before running this code so you're not creating a loop.

     

     

    HTH

     

     

    Kevin
  • HI all.

     

    This is REALLY helpful, but I'm wondering if you could add one more thing to Kevin's iRule... I'd like to check node availability and redirect only if the node is up and skip that node and go on to the next if it's down. I was trying to use LB:status (preferred because then I shouldn't need a pool?) or active_members, but I'm not able to get it working. I think there are good ways to use this iRule and any help is greatly appreciated!

     

    Thanks.

     

    Kevin

     

  • I'd like to check node availability and redirect only if the node is up and skip that node and go on to the next if it's down.can you try something like this?

    [root@ve10:Active] config  b rule myrule list
    rule myrule {
       when RULE_INIT {
        Round robin counter
       set static::c 0
    
        Round robin node
        www1.url.com = 200.200.200.101
        www2.url.com = 200.200.200.111
        www3.url.com = 200.200.200.103
        www4.url.com = 200.200.200.113
       unset static::node
       set static::node(0) "200.200.200.101"
       set static::node(1) "200.200.200.111"
       set static::node(2) "200.200.200.103"
       set static::node(3) "200.200.200.113"
    }
    
    when HTTP_REQUEST {
        Pick up round robin node
       set try 0
       while { [LB::status node $static::node($static::c)] ne "up" and $try < [array size static::node]} {
          if { $static::c == [expr {[array size static::node] - 1}] } {
             set static::c 0
          } else {
             incr static::c
          }
          incr try
       }
    
        Action when all nodes are down
       if { $try == [array size static::node] } {
          HTTP::respond 200 content "sorry we are not ready" noserver
          return
       }
    
        Send HTTP redirection
       switch $static::c {
          0 { HTTP::redirect "http://www1.url.com" }
          1 { HTTP::redirect "http://www2.url.com" }
          2 { HTTP::redirect "http://www3.url.com" }
          3 { HTTP::redirect "http://www4.url.com" }
       }
    
        Move to next round robin node
       if { $static::c == [expr {[array size static::node] - 1}] } {
          set static::c 0
       } else {
          incr static::c
       }
    }
    }