从erlang进程获取响应

时间:2012-05-14 12:38:00

标签: concurrency erlang distributed-computing

我有一个erlang项目,它向我的应用程序发出大量并发SOAP请求。目前,它受限于可用的节点数,但我想调整它,以便每个节点一次可以发送多个消息。

我已经解决了这个问题,但我不知道如何从运行SOAP请求的进程中获得响应。

这是我试图用来做多个线程的函数:

batch(Url, Message, BatchSize) ->
    inets:start(),

    Threads = for(1, BatchSize, fun() -> spawn(fun() -> attack_thread() end) end),
    lists:map(fun(Pid) -> Pid ! {Url, Message, self()} end, Threads).

此功能由启动压力测试仪的人员调用,在我们网络中的每个节点上调用。它被连续调用,直到所有请求的SOAP请求数量都已发送并定时。

这是通过批处理方法发送消息的attack_thread:

attack_thread() ->
 receive
    {Url, Message, FromPID} ->
        {TimeTaken, {ok, {{_, 200, _}, _, _}}} = timer:tc(httpc, request, [post, {Url, [{"connection", "close"}, {"charset", "utf-8"}], "text/xml", Message}, [], []]),
        TimeTaken/1000/1000.
 end

如您所见,我希望它返回SOAP请求所用的秒数。但是,erlang的消息传递(Pid ! Message)不会返回任何有用的信息。

我怎样才能得到结果?

1 个答案:

答案 0 :(得分:1)

每个attack_thread()个线程都可以简单地在操作batch/3函数的进程的邮箱中删除一条消息:

 FromPid ! {time_taken, self(), TimeTaken / 1000 / 1000}.

但是你需要收集结果:

 batch(Url, Message, BatchSize) ->
  inets:start(),

  Pids = [spawn_link(fun attack_thread/0) || _ <- lists:seq(1, BatchSize],
  [Pid ! {Url, Message, self()} || Pid <- Pids],
  collect(Pids).

 collect([]) -> [];
 collect(Pids) ->
   receive
     {time_taken, P, Time} ->
       [Time | collect(Pids -- [P])]
   end.

其他一些评论:你可能想要spawn_link / 1。如果有什么东西在途中死亡,你希望整个事情都会消亡。另外,请务必稍微调整一下httpc,以便更有效。您可能还想查看basho_bench或tsung。

最后,您可以直接使用闭包,而不是传递URL和消息:

 attack_thread(Url, Message, From) -> ...

所以你的产卵是:

 Self = self(),
 Pids = [spawn_link(fun() -> attack_thread(Url, Message, Self) end) || _ <- ...]

它避免在开始时传递消息。