[erlang-questions] Recommended Application Structure
Robert Raschke
rtrlists@REDACTED
Sun Oct 23 22:50:50 CEST 2011
On Sun, Oct 23, 2011 at 6:59 PM, Matthew Evans <mattevans123@REDACTED>wrote:
>
> Hi List,
>
> I've often wondered what is the correct (as in idiomatic Erlang) way to
> structure an sufficiently complex service in Erlang?
>
> Obviously a simple service would be a single application, with a supervisor
> hierarchy something like:
>
> app_foo
> |
> foo_sup
> |
> gen_servers
>
>
> Let's suppose you have a complex service to deploy (that does related, but
> functionally separate tasks), what is normal:
>
>
> 1) Separating the complexity as multiple apps (i.e. 2 .app files and beam
> files in separate ebin directories):
>
> app_foo app_bar
>
> | |
>
> foo_sup bar_sup
>
> | |
>
> gen_servers gen_servers
>
>
> Or...
>
>
> 2) A single app with multiple (hierarchical) supervisors (i.e. 1 .app file,
> all beam files in the same ebin directory):
>
>
> app_foobar
> |
> foobar_sup
> |
> ---------------
> | |
> foo_sup bar_sup
> | |
> foo's bar's
> gen_servers gen_servers
>
>
> Seems like the preference is towards example 2; but to me this means that
> you can't easily decompose and separate functionality apart. It also means
> that messaging can jump across supervisors making for somewhat messy
> interfaces (plus having to cross supervise/link gen_servers that are
> separated by different supervisors).
>
> Thanks
>
> Matt
>
>
A complex package, in my mind, is made up of a collection of Erlang
applications, each of which encapsulates a sub-system of the whole. These
sub-systems are either passive (i.e., "just" libraries, in the vein of
stdlib and kernel) or active (an Erlang application that has a start
function defined in the .app file). For the active components, I tend to go
with a simple app-sup-[gen_*] layout. The overall startup is defined through
the .rel file and the individual .app files. But for this approach you need
to use the release building facilities of Erlang. Those are not hard, but do
take a bit of exercise to get a good grip on.
Sometimes, in some of the more complex sub-systems, you can end up with a
more complex supervision tree (multiple supervisors, multiple gen_*
components, in varying levels of supervision). An example would be a kind of
dynamic worker pool, where you could have a top level supervisor in charge
of an "organisor" (who brings workers to life to do stuff) and a supervisor,
and the latter will look after the workers created by the "organisor".
But your overriding architectural approach needs to use sub-system divisions
that make sense when you talk about them using normal language. It is
frightfully easy to start dividing your code into "unnatural" divisions,
based on overly abstract concepts like "Utility library" or "Framework" or
some such. The more you are able to keep the divisions (and naming, which is
way harder than it seems) based on the actual real application, the better
you will later understand why the architecture looks the way it does.
All a bit abstract, sorry. But hopefully still helpful.
Robby
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://erlang.org/pipermail/erlang-questions/attachments/20111023/8610cd09/attachment.htm>
More information about the erlang-questions
mailing list