I have just switched to self-hosted Anvil mainly for performance and connection speed.
Before switching, when I called a function from server code repeatedly, it was being distributed randomly on my ~5 uplink computers. That was cruical for me for load-balancing.
After I switched to self-hosted instance, although all uplinks reporting they are connected, all repeated function calls goes to a single uplink (I guess randomly)
Is there anything I’m missing or maybe a setting somewhere?
I think that is the expected normal behavior, and what you were experiencing previously was actually aberrant behavior. (A nice way of saying, “It’s a feature, not a bug” )
I think the normal behavior is supposed to be like:
The last uplink that is connected to anvil and registered that specific named function will be the one used. EDIT: This is no longer how it works for ‘normal’ cloud-hosted anvil ( see @stefano.menci s post below) but as of the time of this edit, -is- apparently how it is working when self hosted.
I bolded the words above, because you can use an argument passed to the function decorator @anvil.server.callable(some_new_function_name)
to change the name of the function as registered, allowing you to call a specific uplink function on a specific machine, if you had a unique identifier for that machine.
for example:
On Alices PC:
machine_name = "Alice_PC"
@anvil.server.callable("example_func" + machine_name )
def example_func():
do_stuff()
return
On Bobs PC:
machine_name = "Bob_PC"
@anvil.server.callable("example_func" + machine_name )
def example_func():
do_stuff()
return
You could then do your own load balancing. Maybe when each of the uplink scripts run they could register themselves in a table or something with a unique ID and when you have a client call an uplink, it could go to the table a pick a registered machine or something. (Either randomly, or use an “in-use” Boolean column or something, that gets reset/released when the function is over.)
Also above, you could programmatically get a unique machine ID using lots of different methods in python, although it might be os specific, but you could even test for that using python.
Google “os uuid python” for more details.
This is the old behavior.
Now the Anvil server does some load balancing by (I think) randomly picking one of the registered uplink scripts.
See here: Multiple Uplinks To Same App - #11
I have 3 uplink servers and I use the machine name suffix to always call server1 if it’s available, if that’s busy I call server2, if that’s busy I call server3. If they all are busy I wait for them to be available. (The script uses resources that cannot be managed by two concurrent scripts on the same machine, and exits immediately if it receives a request while it’s already processing another one).
This allows me to always go to server1 and check if there is a problem because that’s the one most likely to process the requests.
If the self-hosted server still has the old behavior, you can simulate a load balancing by using unique names for the functions and randomly picking one of them. The problem is that if one of them is down, you only know it after the call fails. And when that machine is back up, you only know if you try to call it.
That was very very helpful.
Next thing I would check was distinguishing uplinks which you already clarified.
Thank you very much.
I have installed the self-hosted instance about 1 month ago (started using yesterday).
TBH, I don’t know how to check if it is the latest. Would appreciate if you can guide me.
I think your final suggestion is similar to Ian’s but instead of choosing randomly, calling them by name might make more sense for better control like “uplink capability” or “uplink priority” etc. that I can keep in a table.
Thank you very much.
Ooh, right you are! The App Server currently just chooses the first applicable uplink, rather than making a random selection.
This behaviour will be updated in the next App Server release, and the App Server will load-balance like the hosted platform does.