[erlang-questions] Architecture: How to achieve concurrency when gen_server:handle_call waits?

Jesper Louis Andersen jesper.louis.andersen@REDACTED
Sun Feb 7 16:14:03 CET 2016

On Sun, Feb 7, 2016 at 2:20 PM, Luke <random.outcomes@REDACTED> wrote:

> 1 - Why isn't this done automatically behind the scenes in gen_server?
> When would you ever not want to free up your gen_server to handle more
> requests?

>From a perspective of increasing concurrency (and thus parallelism) this
model is alluring. But the strength of processing one message at a time in
order is that handling messages linearize. You are sure handling one
message is either going to succeed--you reach the next state invariant and
is ready for the next message--or fail. Since the gen_server is the sole
owner of the data it processes, there is no room for data races. Many parts
of a larger system benefit a lot from this simple model and it scales up to
a point.

> 2 - Is it best practice to spawn each new process under the gen_server, a
> supervisor somewhere, or not all?

This .. depends. Usually the question is "how do you want your newly
spawned processes and the process tree to behave when something goes
wrong?". Running under the gen_server usually means that one failure means
failure of all. Running in a simple-one-for-one supervisor as a sibling to
the gen_server lets you handle individual errors more gracefully (also set
monitors on the workers in this case).

> 3 - If your gen_server is being flooded with messages, would one viable
> solution to achieve concurrency be creating say 10 of the same gen_server
> under a supervisor, and having any processes passing messages to this "job"
> randomly pick one, effectively using probability to reduce traffic to each
> by 1/10 - is there a library/methodology for doing this kind of thing
> already?

Yes. There are multiple solutions and they have different failure semantics
and different semantics when loaded with more requests than they can
handle, or with jobs of varying latency. Can the library batch requests
which are equivalent? There is usually no good one-size-fits-all here. And
this is the main questions you should ask of any such library.

4 - This seems like it would be a common piece of code, is this bundled
> into OTP somewhere? Is this situation what I'm supposed to use gen_event
> for? Or if I'm completely wrong, what is the actual way programs like yaws
> achieve high concurrency, as reading the source code has not revealed the
> answer to me.

If you read the above remarks, you understand why it is hard to come up
with a good design solution everyone would be happy with. You get the tools
to build such a solution, but no solution.

gen_event is actually two kinds of modules: an event manager which is an
endpoint for publishing events, and event handlers, which runs as part of
the event managers context subscribing to events as they come in and doing
work on the event. The model is very suitable for loosely coupling events
from one application into another as you can dynamically install and remove
such handlers. One application contains the event manager and the other
application installs a handler module so it can get notified when such
events occur.

The built-in alarm_handler in Erlang is a good example of a gen_event
system: alarms in the system can be set and cleared, and you can then
subscribe to alarms in order to react to those. An application could
subscribe to the alarm that you lost database connectivity and change its
behavior accordingly. Once the alarm clears, you can resume normal
operation. Another good alarm is "some process is using more than 5% of
available memory". And so on.

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://erlang.org/pipermail/erlang-questions/attachments/20160207/95c07307/attachment.htm>

More information about the erlang-questions mailing list