2012-10-23 29 views
3

这些都是我在二郎第一步这个新手的问​​题:)我产生一个新的Erlang进程为每个Redis的请求,这很遗憾没有什么,我想(“太多的进程”在32K Erlang进程),但是如何将进程的数量限制到例如最大。 16?二郎 - 太多进程

-module(queue_manager). 
-export([add_ids/0, add_id/2]). 

add_ids() -> 
    {ok, Client} = eredis:start_link(), 
    do_spawn(Client, lists:seq(1,100000)). 

do_spawn(Client, [H|T]) -> 
    Pid = spawn(?MODULE, add_id, [Client, H]), 
    do_spawn(Client, T); 

do_spawn(_, []) -> none. 

add_id(C, Id) -> 
    {ok, _} = eredis:q(C, ["SADD", "todo_queue", Id]). 
+2

可选地可以使用增加的进程数在+ P标志:http://erlang.org/pipermail/erlang-questions/2002-December/006329.html – hexist

回答

5

尝试使用Erlang的pg2 module。它允许您轻松创建进程组并提供API以获得组中最接近的(或随机)PID。

下面是eredis客户端的处理组的例子:

-module(redis_pg). 

-export([create/1, 
     add_connections/1, 
     connection/0, 
     connections/0, 
     q/1]). 

create(Count) -> 
    % create process group using the module name as the reference 
    pg2:create(?MODULE), 
    add_connections(Count). 

% recursive helper for adding +Count+ connections 
add_connections(Count) when Count > 0 -> 
    ok = add_connection(), 
    add_connections(Count - 1); 
add_connections(_Count) -> 
    ok. 

add_connection() -> 
    % start redis client connection 
    {ok, RedisPid} = eredis:start_link(), 
    % join the redis connection PID to the process group 
    pg2:join(?MODULE, RedisPid). 

connection() -> 
    % get a random redis connection PID 
    pg2:get_closest_pid(?MODULE). 

connections() -> 
    % get all redis connection PIDs in the group 
    pg2:get_members(?MODULE). 

q(Argv) -> 
    % execute redis command +Argv+ using random connection 
    eredis:q(connection(), Argv). 

以下是在上述行动模块的一个例子:

1> redis_pg:create(16). 
ok 
2> redis_pg:connection(). 
<0.68.0> 
3> redis_pg:connection(). 
<0.69.0> 
4> redis_pg:connections(). 
[<0.53.0>,<0.56.0>,<0.57.0>,<0.58.0>,<0.59.0>,<0.60.0>, 
<0.61.0>,<0.62.0>,<0.63.0>,<0.64.0>,<0.65.0>,<0.66.0>, 
<0.67.0>,<0.68.0>,<0.69.0>,<0.70.0>] 
5> redis_pg:q(["PING"]). 
{ok,<<"PONG">>} 
+0

您可能要添加的监督恢复坠毁的连接。你如何确保你得到的小组成员不忙?您正在接近管理两者的连接池。 – Tilman

+0

将进程监视添加到'DOWN'消息的eredis连接是一个好主意,因此您可以重新向该组添加连接。如果你想要最少的繁忙连接,你可以修改'connection'函数遍历所有的pg成员,并使用erlang:process_info(Pid,message_queue_len)来查找最小队列的进程。 – lastcanal

1

您可以使用一个主管,推出每个新进程(您的例子看来你应该使用simple_one_for_one策略):

supervisor:start_child(SupRef, ChildSpec) -> startchild_ret()

您可以使用功能

supervisor:count_children(SupRef) -> PropListOfCounts访问,然后到进程计数。

结果是形式的proplist这样

[{specs,N1},{active,N2},{supervisors,N3},{workers,N4}](顺序不保证!)

如果您想了解活动进程的详细信息,你也可以使用

supervisor:which_children(SupRef) -> [{Id, Child, Type, Modules}]但这当主管管理“大量”儿童时不推荐。

1

你基本上是“你自己”当你实施限制。有些工具可以帮助你,但我认为一般问题“我怎么避免产生太多的过程?”仍然成立。诀窍是跟踪进程数量。

一个Erlang-惯用的方法是有一个包含计数器的过程。无论何时你想产生一个新的过程,你都会问你是否允许通过注册对令牌的需求来做到这一点。然后等待计数过程回复给您。

的计数处理,然后一个漂亮的模块化家伙保持你的限制。