我有一个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
)不会返回任何有用的信息。
我怎样才能得到结果?
答案 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) || _ <- ...]
它避免在开始时传递消息。