Как мне сказать супервизору запустить 1000 экземпляров определенного gen_server? - PullRequest
0 голосов
/ 05 октября 2018

В рамках решения задачи, требующей большого объема вычислений, я хочу, чтобы 1000 gen_servers выполняли небольшую задачу и обновляли глобальную базу данных.Как я могу добиться этого в Erlang OTP?В большинстве примеров супервизор контролирует только один gen_server.Может ли супервизор контролировать более тысячи экземпляров одного и того же gen_server?

Например, скажем, я хочу найти максимум очень длинного массива, и каждый экземпляр gen_server должен создавать работу над частью массива и обновлять глобальный минимум.

Ответы [ 2 ]

0 голосов
/ 06 октября 2018

Как сказал Паскаль, можно запустить набор или дочерние числа, но описанный вами вариант использования, вероятно, будет работать лучше со стратегией simple_one_for_one , поскольку все дочерние элементы одинаковы.Это позволяет добавлять столько детей того же типа, сколько необходимо, с меньшими затратами.У gen_servers есть издержки, и хотя он не слишком велик, когда вы говорите о 1000 процессах, обрабатывающих числа, это имеет значение.

Если ваши процессы будут делать что-то очень простое, и вы хотите, чтобы это было быстро, я бы не стал использовать gen_servers, а просто порождал процессы.Для реальной власти вам придется порождать процессы на разных узлах, используя spawn / 4 , чтобы использовать больше ядер.Если вы используете машины в разных местах, вы также можете использовать шину сообщений в качестве балансировщика нагрузки для распределения работы между узлами.Все зависит от того, сколько работы вам нужно сделать.

Также имейте в виду, что Эрланг не самый лучший для хруста чисел.Вы можете использовать C-код для выполнения хруста и заставить каждый процесс Erlang, который вы порождаете / каждого потомка, вызывать nif .

0 голосов
/ 05 октября 2018

Возможно ли это: да.Например, вы можете создать пул из 1000 процессов со следующим супервизором:

-module (big_supervisor).

-export([start_link/0]).

-behaviour(supervisor).
-export([init/1]).

start_link() ->
    supervisor:start_link({local, ?MODULE}, ?MODULE, {}).

%% @private
init({}) ->
    Children = create_child_specs(1000),
    RestartStrategy = {one_for_one, 5, 10},
    {ok, {RestartStrategy, Children}}.

create_child_specs(Number) ->
    [{{child_process,X},{child_process, start_link, []},permanent, 5000, worker,[child_process]} || X <- lists:seq(1,Number)].

Это хорошая архитектура, я не знаю.До сих пор я обнаружил 2 вида архитектуры:

  • Одна с ограниченной и хорошо идентифицированной (по роли) дочерью
  • Одна с некой фабрикой процессов, динамически создающей как можно больше детейпри необходимости по требованию, используя стратегию simple_one_for_one и функции start_child/2 terminate_child/2.

Следует также отметить, что супервизоры не обязательны, если вы хотите порождать процессы.В вашем объяснении кажется, что процессы могут быть созданы за очень ограниченное время, чтобы параллельно что-то вычислять.Два замечания в этом случае:

  • не стоит создавать больше процессов, чем количество потоков, которые будут эффективно работать параллельно на вашей виртуальной машине.
  • одно исключение - если работаДля достижения в каждом процессе придется ждать внешней информации, например, о возврате внешней базы данных.В этом случае может быть интересно порождать больше процессов, оптимальное количество зависит от внешних ограничений доступа.
...