How to start distributed Erlang app without starting dependencies at every node?

432 views Asked by At

I tried to run a simple app in a distributed manner to test failover-takeover features but failed.

What I want to:

The application is myapp_api with a rest api, it has myapp application as a dependency. I want to start myapp_api on 3 nodes, I want the whole app (myapp_api + myapp) to be working only at one node at the same time.

What is wrong:

The main app (myapp_api) works as expected: only at one node with failover and takeover. But for some reason depended myapp always starts at every node. I want it to be working only at one node at the same time.

What I do:

My config for the first node as an example.

[
    {kernel,
    [{distributed, [{myapp_api,
        1000,
        ['n1@myhost', {'n2@myhost', 'n3@myhost'}]}]},
        {sync_nodes_optional, ['n2@myhost', 'n3@myhost']},
        {sync_nodes_timeout, 5000}
    ]}
].

I call erl -sname nI -config nI.config -pa apps/*/ebin deps/*/ebin -s myapp_api at every node.

1

There are 1 answers

2
I GIVE TERRIBLE ADVICE On BEST ANSWER

Now this gets a bit confusing because you say:

I want to start myapp_api on 3 nodes, I want the whole app (myapp_api + myapp) to be working only at one node at the same time.

and you add:

The main app (myapp_api) works as expected: only at one node with failover and takeover. But for some reason depended myapp always starts at every node.

In the first paragraph you say myapp_api should run everywhere, on the second quote you say it works as intended by booting on one node at a time.

I'll be assuming here that you want the whole set-up to be a failover, not just the top-level app and I just got confused on the first paragraph.

The config file you use shows what happens:

[{kernel,
  [{distributed, [{myapp_api,
    1000,
    ['n1@myhost', {'n2@myhost', 'n3@myhost'}]}]},
    {sync_nodes_optional, ['n2@myhost', 'n3@myhost']},
    {sync_nodes_timeout, 5000}
]}].

The important bit is that myapp_api has the nodes ['n1@myhost', {'n2@myhost', 'n3@myhost'}] defined. This order means it runs on n1@myhost in top priority, and then on the other nodes with equal priority if there is a failover.

The thing is that none of the dependencies are distributed in the same way, and can therefore be expected to be running everywhere.

You should only need to expand on that config file to get it to work. Here I've done it and reindented it to show its structure better:

[{kernel,
  [{distributed, [
     {myapp_api, 1000, ['n1@myhost', {'n2@myhost', 'n3@myhost'}]},
     {myapp, 1000, ['n1@myhost', {'n2@myhost', 'n3@myhost'}]},
   ]},
   {sync_nodes_optional, ['n2@myhost', 'n3@myhost']},
   {sync_nodes_timeout, 5000}
]}].

I haven't tested it directly, but I'm pretty sure this will work.

If what you wanted was for myapp_api to be everywhere but for myapp to run in one place, you could use global registration, give a name to myapp's public-facing process, get myapp_api to call these. myapp_api would then be able to route traffic to wherever myapp is when supported with the following config:

[{kernel,
  [{distributed, [
     {myapp, 1000, ['n1@myhost', {'n2@myhost', 'n3@myhost'}]},
   ]},
   {sync_nodes_optional, ['n2@myhost', 'n3@myhost']},
   {sync_nodes_timeout, 5000}
]}].

(See how myapp is the only app getting a distribution profile? Other apps will get to run on all nodes)