Forum Discussion

walkman69's avatar
walkman69
Icon for Altostratus rankAltostratus
Mar 25, 2024
Solved

URL Distribution

I received a request as to the possibility to or distribute traffic for one url to multiple urls (round-robin, least connections, or even just randomly ) but never exceed 50 connections to each one. I am struggling to find the best way to do this, if even feasible. This would not be sending to different pools/server, but to different "forms" on the same server/pool. Any guidance anyone can provide would be greatly appreciated.

Here is an a visual  example of what they are trying to accomplish:

https://forms.dummywebsite.com/form would distribute traffic to the following without without a redirect or end user noticing a url change in their browser.

                                                                    >       https://forms.dummywebsite.com/form1
                                                                    >       https://forms.dummywebsite.com/form2
                                                                    >       https://forms.dummywebsite.com/form3
https://forms.dummywebsite.com/form        >       https://forms.dummywebsite.com/form4
                                                                    >       https://forms.dummywebsite.com/form5
                                                                    >       https://forms.dummywebsite.com/form6

 

It would be required that each form would never more that 50 connections. I have found a potential irule  candidate pasted below from another post (thanks The_Bhatmann - distribute-load-based-on-uri) that contains a counter that may be able to be adjusted for this, but not sure it really fits the bill. It would need to monitor all the connections to make sure each connection has not exceeded 50 before more traffic is sent to it. All my other google-foo has failed.

 

when RULE_INIT {
   set counter 0
}
when CLIENT_ACCEPTED {
    if {$::counter <= 7} {
     The first 7 connections go to Server A for URI 1
      pool  member  
      incr $::counter
   } elseif {$::counter <= 10 } {
      The next 3 connections go to server B for URI 2
      pool  member  
      incr $::counter
   } else {
     Reset the counter when 11th connection is reached and go to SERVER A for URI 1
     set $::counter 0
      pool  member  
   }
}  

 

 

Thanks for any help/Guidance. Any input is much appreciated

  • JRahm's avatar
    JRahm
    Mar 26, 2024

    Not at all tested or optimized or secured against injection with the table commands, but to get the juices flowing I threw this together. Not 100% confident it'll work and I don't have time until end of the week to flesh out and test, but it is possible to achieve what you're after. That said, it'll be a support nightmare to grow with the needs of the business since it's not a well-defined problem or scale, so I would push back against this particular ask.

    when HTTP_REQUEST priority 500 {
        if { [string tolower [HTTP::path]] == "/form"} {
            foreach form [list form1 form2 form3 form4 form5 form6] {
                if { [table lookup $form] < 50 } {
                    table incr $form 1
                    HTTP::uri /$form
                    set current_form $form
                    break
                }
            }
        }
    }
    when HTTP_REQUEST priority 501 {
        if { [string tolower [HTTP::path]] == "/form" } {
            HTTP::respond 429 content "<html><body><p>All forms at max of 50 requests</p></body></html>" 
        }
    }
    when HTTP_RESPONSE {
        table incr $current_form -1
    }

     

6 Replies

  • hi walkman69 is the number of forms static or dynamic? For example, is the list form1 -> form6, and therefore 300 connections max, or just form1 -> form(n) and incrementing every 50 connections? If the latter, as connections bleed from previous forms, do you want to send new requests to those?

     

    Also I should mention that example is very old. Logic isn't bad, but the use of global variables is, and pins all requests for that virtual server to a single TMM.

    • walkman69's avatar
      walkman69
      Icon for Altostratus rankAltostratus

      Hi JRahm!

      Thanks for the reply and the heads-up on the example.  At this point the number of forms will be static, but of course as the business needs, that could change in the future. Yes, as the connections bleed from the forms new requests can be sent to them.

      • JRahm's avatar
        JRahm
        Icon for Admin rankAdmin

        Not at all tested or optimized or secured against injection with the table commands, but to get the juices flowing I threw this together. Not 100% confident it'll work and I don't have time until end of the week to flesh out and test, but it is possible to achieve what you're after. That said, it'll be a support nightmare to grow with the needs of the business since it's not a well-defined problem or scale, so I would push back against this particular ask.

        when HTTP_REQUEST priority 500 {
            if { [string tolower [HTTP::path]] == "/form"} {
                foreach form [list form1 form2 form3 form4 form5 form6] {
                    if { [table lookup $form] < 50 } {
                        table incr $form 1
                        HTTP::uri /$form
                        set current_form $form
                        break
                    }
                }
            }
        }
        when HTTP_REQUEST priority 501 {
            if { [string tolower [HTTP::path]] == "/form" } {
                HTTP::respond 429 content "<html><body><p>All forms at max of 50 requests</p></body></html>" 
            }
        }
        when HTTP_RESPONSE {
            table incr $current_form -1
        }

         

  • Hi walkman69,

    I am randomly guessing, that each form1-6 is server by a different pool member. If my assumption is right, you can set a session limit per node and use Least Connections method for load balancing.

    root@(awaf)(cfg-sync Standalone)(Active)(/Common)(tmos)# list ltm node 10.0.2.50 
    ltm node 10.0.2.50 {
        address 10.0.2.50
        connection-limit 50
    }
    

    Then I would do the URL rewriting on the web server in the backend. Doing application logic on the BIG-IP is possible, but sometimes it's just... meh... Uti, non abuti.

    Maybe you can explain your requirements a bit more in details, so we can suggest a better solution.

    KR
    Daniel

     

    • walkman69's avatar
      walkman69
      Icon for Altostratus rankAltostratus

      Hi Daniel_Wolf! This is not node/member specific. All forms will reside on all servers in the same pool(s) and those servers it is just this one particular form/webpage that needs this type of distribution as the servers also handle traffic for other websites, so the connection limit cannot be set on a node basis. I definitely agree this is something that should be done on the web server itself, the dev team just wants to explore all options.