Forum Discussion

j-boelhouwer_11's avatar
j-boelhouwer_11
Icon for Nimbostratus rankNimbostratus
Jan 05, 2016

iRule for HTTP redirect, destination address persistence based on HTTP::URI

Hi All,

 

I have been using an iRule to elect a pool member from a pool which is closest to the client based on the client ip address. Then an HTTP redirect would be send to that client to connect to the actual server. This works well but now we are in the need of another type of iRule where we can optimize our caches. But since the web directories and files are dynamic (adaptive bitrate streaming (HLS)) we cannot use the folders or paths in the iRule code...

 

Lets say I have two caching reverse proxies (node1 and node2) and three clients (client1, client2 and client3) and two HLS encoded movies (movie1 and movie2).

 

If client1 requests movie1 "http://{BigIp_f5_ltm_VIP}/vod/movie1/movie1.m3u8" I would like to have an HTTP redirect send by the load balancer back to the client to go to "http://{node1_ip}/vod/movie1/movie1.m3u8".

 

Then if client 2 requests the same url "http://{BigIp_f5_ltm_VIP}/vod/movie1/movie1.m3u8" an HTTP redirect message would need to be send back to the client to connect to node1 again (because client1 was send there before).

 

Now if client3 comes by for movie2 "http://{BigIp_f5_ltm_VIP}/vod/movie2/movie2.m3u8" an HTTP redirect to go to node2 would need to be send back to the client.

 

Basically this would mean that I need HTTP redirection with destination ip address persistence based on the HTTP::URI. How can I do this?

 

Thanks in advance,

 

Jeroen

 

5 Replies

    • Kai_Wilke's avatar
      Kai_Wilke
      Icon for MVP rankMVP
      Hi Jeroen, using a hash based calculation would already make your initial election completely random, but on the other wouldn't require memory to store the [table] records. So if the randomness is not an issue, then go for it. Its a much better approach then... Cheers, Kai
  • Hi Jeroen,

    you could store the previous elections results for a given URI/Path into LTMs memory based [table] and then query the [table] on consecutive request before electing again.

     

    when RULE_INIT {
        set static::table_lifetime 86400 ; One day
    }
    
    when HTTP_REQUEST {
        if { [HTTP::path] starts_with "/vod/" } then {
            if { [set location [table lookup -notouch "redir_[HTTP::path]"]] ne "" } then {
                HTTP::redirect $location
            } else {
    
                 Insert your election code here
                 Change your code so that it stores the elected location into $location
    
                table set "redir_[HTTP::path]" $location indef $static::table_lifetime
                HTTP::redirect $location
            }
        }
    }
    

     

    Cheers, Kai

  • Hi Kai,

    Thanks for your ideas.

    Using the hash election there is no need to store the information in the memory since there will not be that many http requests hitting the LTM. It is only the first HTTP request a client makes. Consequent requests as derived from the m3u8 playlist are made to the edge server directly. So If there are say 20.000 clients in 1 hour requesting the initial m3u8 playlist then the iRule will be fired only 5.4 times per second on average (if the requests are evenly spread out) I have seen similar iRule executions well above 1000 tps. For now I have 2 edge nodes and the following iRule. For each request

     

     Election Hash iRule
     Version 1.0 Jan 5th 2016
    
     MD5 calculation of Server + URI
     Rule selects Server that scores highest
    
     S = Current high score
     N = Node being evaluated
     W = Winning node
    
    
    when HTTP_REQUEST {       
        if {[active_members -list pool_edge_nodes] > 0 }   {
            if { (([HTTP::method] eq "GET") && ([HTTP::uri] contains ".m3u8")) } {
                 Election Randomizer
                 Using md5 function + http::uri to generate a score. The highest wins.
                set S ""
                set R ""
                foreach N [active_members -list pool_edge_nodes] {
                if { [md5 $N[HTTP::uri]] > $S } {
                    set S [md5 $N[HTTP::uri]]
                    set W $N
                    }
                }
                log "winning server: $W"
    
                 Generate redirect
                set edgeip [lindex $W 0]
                set url "http://$edgeip[HTTP::uri]"
    
                 Send Redirect message
                HTTP::redirect "$url"
                log "[IP::client_addr] - Redirected to $url"
            } else {
                 Send Service Unavailable message
                HTTP::respond 503
                log "[IP::client_addr] - Not redirected, no edge node available"
            }
        } else {
             Send Service Unavailable message
            HTTP::respond 404
            log "[IP::client_addr] - Not redirected, not a valid request"
        }
    }   
    

     

    Thanks,

    Jeroen

    • Kai_Wilke's avatar
      Kai_Wilke
      Icon for MVP rankMVP
      As i said in my last comment a stateless solution based on hashes/checksums should be alway prefered if possible. I also don't believe that 5,4 RPS would have a noticable impact on your box. But if performance would become a problem in the future, then fell free to come back to devcentral, so that we could optimize your code a little bit. On the first sight your rule has the potential to save some cycles... ;-) Cheers, Kai