【问题标题】:How do I tell supervisor to start 1000 instances of a specific gen_server?如何告诉主管启动特定 gen_server 的 1000 个实例?
【发布时间】:2019-03-10 13:29:03
【问题描述】:

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

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

【问题讨论】:

    标签: erlang erlang-supervisor gen-server


    【解决方案1】:

    有没有可能:是的。例如,您可以使用以下主管创建一个包含 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 函数按需动态创建任意数量的子代。

    还要注意,如果您想生成进程,监督者不是强制性的。在您的解释中,似乎可以在非常有限的时间内创建进程,以便并行计算某些东西。本例有两点说明:

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

    【讨论】:

      【解决方案2】:

      就像 Pascal 所说,可以开始一个或多个孩子,但你描述的用例可能会更好地使用 simple_one_for_one 策略,因为所有孩子都是一样的。这使您可以根据需要以较小的成本添加尽可能多的相同类型的子代。 gen_servers 有开销,即使它不是太大,当您谈论 1000 个处理数字的进程时,它也会产生影响。

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

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

      【讨论】:

        猜你喜欢
        • 2011-06-18
        • 2016-08-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-10-15
        • 1970-01-01
        • 2021-09-10
        相关资源
        最近更新 更多