antipatreal
antipatreal

Reputation: 139

Erlang supervisor processes

I have been learning Erlang intensively, and after finishing 'Programming Erlang' from Joe Armstrong, there is one thing that I keep coming back to.

In my mind a Supervisor spawns One process per child handler. So each declared gen_server type handler will run as a separate process.

What happens if you are building a tiny web server and you want each requests to be its own process. Do you still conform to OTP principles and use a gen_server somehow (how ?), or do you create your own behaviour?

How does Cowboy handle this for eg. ? Does it still use gen_server ?

Upvotes: 0

Views: 645

Answers (2)

Pascal
Pascal

Reputation: 14042

It is a common pattern to spawn one server per client in erlang, You will then use a supervisor using the simple_one_to_one strategy for the children servers. This allows to ask the server to start a server on_demand. Generally this is used when you don't know how many processes you will need, and when the processes are independent (a crash of one process should not impacts the other).

There is a very good information in the site learningyousomeerlang.com (LYSE supervisor chapter). the whole site is worth to read.

Upvotes: 2

zxq9
zxq9

Reputation: 13144

tl;dr: I find that trying to figure out the "correct" supervision structure a the beginning of a project is a form of premature optimization.

The "right" way to design your supervision tree depends on what the worker parts of your application are doing. In the case of a web server I would probably first explore something along the lines of:

  • top supervisor (singular)
    • data service supervisor (one per service type)
      • worker pool (all workers under the service sup)
    • client connection supervisor (one)
      • connection worker pool (or one per connection, have to play with it to decide)
    • logical supervisor (as appropriate -- massive variance here, depending on problem domain)
      • workers or supervisors (as appropriate -- have to explore/know the problem domain to have any idea how this should be structured)

So that's several workers per supervisor type at the lower level. I haven't used Cowboy so I don't know how it is organized. The point I'm trying to make is that while the mechanics of handling data services serving web pages are relatively trivial, the part of the system that actually does the core problem-solving work might not be and this is going to dictate everything interesting about the system.

It is a bad thing to have your problem-solving bits mixed in the same module as your web-displaying or connection handling bits. Ideally you should be able to use the same logic units in a native application, a web application and a networked service without any changes.

Ultimately the answer to whether you should have 1:1 supervisors to workers or 1:n depends on what you're doing and what restart strategy gives you the best balance among recovery to a known consistent state, latency felt by the user, and resource usage.

One of my favorite things about Erlang is that I can start with a naive supervisor structure like the one above, play with it until I see where its not so good, and rather easily switch things around and experiment with alternatives without fundamentally altering my system much. (The same goes for playing with alternative data representations if you write proper abstractions around them.) So first, get something that works in testing. Then load it up and see if you can break it. Then start worrying about the details, after you understand where the problems actually are.

Upvotes: 3

Related Questions