我如何告诉主管启动特定 gen_server 的 1000 个实例?
How do I tell supervisor to start 1000 instances of a specific gen_server?
作为解决计算密集型任务的一部分,我希望有 1000 个 gen_servers 执行小任务并更新全局数据库。我怎样才能在 erlang OTP 中实现这个?在大多数示例中,主管仅监督一个 gen_server。一个监督者可以监督超过一千个相同的实例吗gen_server?
例如假设我想找到一个极长数组的最大值,每个 gen_server 实例应该在数组的一部分上创建工作并更新全局最小值。
是否可以:可以。例如,您可以使用以下主管创建一个包含 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)].
是不是一个好的架构,我不知道。到目前为止,我发现了两种架构:
- 一个孩子数量有限且身份明确(按角色)
- 一种流程工厂,根据需要动态创建尽可能多的 children,使用
simple_one_for_one
策略和 start_child/2
terminate_child/2
函数。
另请注意,如果您想生成进程,主管不是强制性的。在您的解释中,似乎可以在非常有限的时间内创建进程,以便并行计算某些东西。在这种情况下有两点说明:
- 不值得在您的 VM 上生成比有效 运行 并行的线程数更多的进程。
- 一个例外是如果在每个进程中实现的工作将不得不等待外部信息,例如外部数据库的return。在这种情况下,产生更多进程可能很有趣,最佳数量取决于外部访问限制。
就像 Pascal 所说的那样,可以开始设置数字或 children,但您描述的用例可能会更好地使用 simple_one_for_one 策略,因为所有 children是相同的。这使您可以根据需要以较小的成本添加尽可能多的相同类型的 children。 gen_servers 有开销,即使不是太大,当您谈论 1000 个处理数字的进程时,它也会有所不同。
如果您的进程将做一些非常简单的事情,并且您希望它很快,我会考虑不使用 gen_servers,而只是生成进程。为了获得真正的力量,您必须使用 spawn/4 在不同的节点上生成进程以利用更多的核心。如果您在不同位置使用机器,您还可以使用消息总线作为负载平衡器来在节点之间分配工作。一切都取决于您需要完成多少工作。
另请记住,Erlang 并不是处理数字的最佳选择。您可以使用 C 代码进行处理,并让每个 Erlang 进程都被您 spawn/each child 调用 nif。
作为解决计算密集型任务的一部分,我希望有 1000 个 gen_servers 执行小任务并更新全局数据库。我怎样才能在 erlang OTP 中实现这个?在大多数示例中,主管仅监督一个 gen_server。一个监督者可以监督超过一千个相同的实例吗gen_server?
例如假设我想找到一个极长数组的最大值,每个 gen_server 实例应该在数组的一部分上创建工作并更新全局最小值。
是否可以:可以。例如,您可以使用以下主管创建一个包含 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)].
是不是一个好的架构,我不知道。到目前为止,我发现了两种架构:
- 一个孩子数量有限且身份明确(按角色)
- 一种流程工厂,根据需要动态创建尽可能多的 children,使用
simple_one_for_one
策略和start_child/2
terminate_child/2
函数。
另请注意,如果您想生成进程,主管不是强制性的。在您的解释中,似乎可以在非常有限的时间内创建进程,以便并行计算某些东西。在这种情况下有两点说明:
- 不值得在您的 VM 上生成比有效 运行 并行的线程数更多的进程。
- 一个例外是如果在每个进程中实现的工作将不得不等待外部信息,例如外部数据库的return。在这种情况下,产生更多进程可能很有趣,最佳数量取决于外部访问限制。
就像 Pascal 所说的那样,可以开始设置数字或 children,但您描述的用例可能会更好地使用 simple_one_for_one 策略,因为所有 children是相同的。这使您可以根据需要以较小的成本添加尽可能多的相同类型的 children。 gen_servers 有开销,即使不是太大,当您谈论 1000 个处理数字的进程时,它也会有所不同。
如果您的进程将做一些非常简单的事情,并且您希望它很快,我会考虑不使用 gen_servers,而只是生成进程。为了获得真正的力量,您必须使用 spawn/4 在不同的节点上生成进程以利用更多的核心。如果您在不同位置使用机器,您还可以使用消息总线作为负载平衡器来在节点之间分配工作。一切都取决于您需要完成多少工作。
另请记住,Erlang 并不是处理数字的最佳选择。您可以使用 C 代码进行处理,并让每个 Erlang 进程都被您 spawn/each child 调用 nif。