Scale umbrella microservices to multiple servers

Recently I was reading this great article about microservices again: Elixir in times of microservices « Plataformatec Blog
It describes how an umbrella app can be deployed separately:

if you want to deploy your a, b and c applications as [a, b] + [c] or [a] + [b] + [c], you will have very little trouble in doing so due to their inherent design and built-in communication.

So each app could be deployed on different serves and they would communicate through the distributed erlang messaging system instead of HTTP. So far so good. The article goes on to describe:

If c requires more instances or the application with user specific concern, then it is reasonable to isolate it and deploy multiple instances of c.

This is actually very interesting as it is a common use case in microservices. You start multiple instances of one microservices and put a load balancer in front of it. When the microservices are using HTTP calls this is sort of simple to realize. But I was wondering how this is done in elixir/erlang when all the nodes are connected directly and not communicating through HTTP.

So we would have one server hosting the application A and two servers hosting application C. How are these system then connected and how are the “rpc calls” to node C load balanced?
The only thing I could find was the erlang pool module: Erlang -- pool Which seems to go into this direction. But I could not find a real example where all of this is implemented.

Has anyone tried something like this?

2 Likes

Depending on how complex and accurate you want the load balancing of the servers you could do something like the following

:rpc.call([Enum.random(Node.list())], Module, Function, Argument)

This is a simple way to distribute load across a set of nodes. If your Node.list() contains nodes that do not have the MFA you want to run you could make a custom function that returns a random node from a group of nodes that do have your function on them.

There is probably some more official way but this is just an idea to get the conversation flowing.

1 Like

Haha, that is actually a very nice and simple solution :+1: which can be wrapped in a helper function. And it would also handle cases where a node goes down and back up.
Of course it does not take into consideration the current load of each system, but a standard round robin load balancers is also not doing this.

Great idea!

1 Like

If you need this kind of control, poolboy to the rescue! There is this elixir school page that might help you: Poolboy · Elixir School

With poolboy you can limit the load to a pool of workers but how would one “route” work loadbalance style with poolboy based on load.

1 Like

I don’t see how to apply a pool manager to the problem of load balancing. A pool manager is used over a pool of resources when the usage of each resource is exclusive and you must check it out until your request for it is complete. Typically with load balancing each node can handle multiple simultaneous requests and a load balancer distributes them.

1 Like

Yep, you are right, didn’t think about it very well, sorry for that. :lol:

:pg2.get_closest_pid looks like it could be used to randomly distribute across a pool of remote worker processes.

2 Likes

Oh nice, This look interesting I have not looked into pg2 that much myself.

1 Like