作为解决计算密集型任务的一部分,我希望有1000个gen_servers执行小任务并更新全局数据库。如何在erlang OTP中实现此目标?在大多数示例中,主管仅监督一个gen_server。主管可以监督同一个gen_server的一千多个实例吗?
例如假设我想找到一个非常长的数组的最大值,并且每个gen_server实例都应在该数组的一部分上创建工作并更新全局最小值。
答案 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。