我如何告诉主管启动特定gen_server的1000个实例?

时间:2018-10-05 05:27:20

标签: erlang supervisor gen-server

作为解决计算密集型任务的一部分,我希望有1000个gen_servers执行小任务并更新全局数据库。如何在erlang OTP中实现此目标?在大多数示例中,主管仅监督一个gen_server。主管可以监督同一个gen_server的一千多个实例吗?

例如假设我想找到一个非常长的数组的最大值,并且每个gen_server实例都应在该数组的一部分上创建工作并更新全局最小值。

2 个答案:

答案 0 :(得分:2)

是否可能:是。例如,您可以使用以下主管创建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)].

这是一个好的架构,我不知道。到目前为止,我发现了两种架构:

  • 一个孩子(根据角色)数量有限且易于识别
  • 具有一种过程工厂的工厂,可以使用simple_one_for_one策略和start_child/2 terminate_child/2函数根据需要动态创建任意数量的子级。

还请注意,如果您想生成流程,则监督员不是强制性的。在您的解释中,似乎可以在非常有限的时间内创建进程,以便并行计算某些内容。在这种情况下有两个说明:

  • 不值得产生更多能够在虚拟机上有效并行运行的线程数量的进程。
  • 一个例外是,如果每个过程中要完成的工作都必须等待外部信息,例如外部数据库的返回。在这种情况下,可能会产生更多的进程,最佳数目取决于外部访问限制。

答案 1 :(得分:2)

就像Pascal所说的那样,可以开始设置一个数字或子代,但是您所描述的用例可能更适合simple_one_for_one策略,因为所有子代都是相同的。这样,您便可以以较小的成本添加所需数量的相同类型的子代。 gen_servers有开销,即使它不是太大,当您谈论1000个进程处理数字时,它也会有所作为。

如果您的进程将做一些非常简单的事情,并且您希望它速度很快,那么我会考虑不使用gen_servers,而只是生成进程。为了获得真正的功能,您必须使用spawn/4在不同的节点上生成进程以利用更多的内核。如果在不同位置使用机器,则还可以使用消息总线作为负载平衡器,以在节点之间分配工作。一切都取决于您需要完成多少工作。

还请记住,Erlang不是处理数字的最佳方法。您可以使用C代码进行运算,并让您生成的每个Erlang进程/每个子进程都调用nif