Exception Erlang-进程太多
这是我在Erlang中的第一步,很抱歉这个新手问题:)我正在为每个Redis请求生成一个新的Erlang进程,这不是我想要的(“太多进程”在32k Erlang进程),而是如何限制进程数量,例如最大16个Exception Erlang-进程太多,exception,concurrency,erlang,process,Exception,Concurrency,Erlang,Process,这是我在Erlang中的第一步,很抱歉这个新手问题:)我正在为每个Redis请求生成一个新的Erlang进程,这不是我想要的(“太多进程”在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,1
-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]).
您可以使用连接池,例如。您可能会感兴趣。您可以使用主管启动每个新流程(对于您的示例,您似乎应该使用简单的“一对一”策略):
supervisor:start\u child(SupRef,ChildSpec)->startchild\u ret()
然后可以使用函数访问进程计数
supervisor:count\u children(SupRef)->counts的proplist
结果是表单的proplist
[{specs,N1},{active,N2},{supervisors,N3},{workers,N4}]
(订单不保证!)
如果需要有关活动进程的更多信息,还可以使用
supervisor:which_children(SupRef)->[{Id,Child,Type,Modules}]
但当一个主管管理“大量”的子项时,不建议这样做。当您实施限制时,您基本上是“独立”的。有一些工具可以帮助您,但我认为“如何避免产生太多进程”这个一般性问题仍然适用。诀窍是在某处跟踪进程计数
Erlang惯用的方法是有一个包含计数器的进程。每当您想要生成一个新进程时,您都会询问它是否允许您通过注册对令牌的需求来生成新进程。然后等待计数过程回复您
然后,计数过程是一个很好的模块,为您维护一个限制。尝试使用Erlang。它允许您轻松创建流程组,并提供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">>}
1>redis\u pg:create(16)。
好啊
2> redis_pg:connection()。
3> redis_pg:connection()。
4> redis_pg:connections()。
[,,,,,,
,,,,,,
,,,]
5> redis_pg:q([“PING”])。
{好的,}
您可以选择使用+P标志增加进程数:您可能希望添加监控以恢复崩溃的连接。你如何确保你的小组成员不忙?您正接近一个同时管理这两个消息的连接池。最好将进程监视添加到eredis连接中,以获取“关闭”消息,这样您就可以向组中重新添加连接。如果您想要最不繁忙的连接,您可以修改连接
函数以迭代所有pg成员,并使用erlang:process\u info(Pid,message\u queue\u len)查找队列最小的进程。