【发布时间】:2012-01-01 16:00:02
【问题描述】:
我一直在玩一个玩具网络服务器,我把它放在重负载下。我发现它的表现非常好,除了一些异常值。以下是相关代码:
init() ->
%Gets the listen socket ({active,false}), generates acceptor threads
case gen_tcp:listen(?LISTEN_PORT, ?TCP_OPTS) of
{ok, Listen} ->
?MODULE:gen_accepts(50,Listen)
end,
?MODULE:supervisor_loop(Listen).
supervisor_loop(LS) ->
receive
_ -> ok
after 60000 -> ok
end,
?MODULE:supervisor_loop(LS).
gen_accepts(0,_) -> ok;
gen_accepts(I,LS) ->
spawn(?MODULE,accept_loop,[LS]),
?MODULE:gen_accepts(I-1,LS).
accept_loop(Listen) ->
case gen_tcp:accept(Listen) of
{ok, Sock} ->
spawn(?MODULE,accept_loop,[Listen]),
?MODULE:process_sock(Sock);
{error,_} -> ?MODULE:accept_loop(Listen)
end.
现在所有 ?MODULE:process_sock(Sock) 所做的只是发送一些文本并关闭连接,没有 IO 或任何东西。但是,当我在其上运行 apache benchmark (ab) 时,大约五分之一的结果如下:
Percentage of the requests served within a certain time (ms)
50% 3
66% 3
75% 4
80% 4
90% 271
95% 271
98% 271
99% 271
100% 271 (longest request)
总共有 20 个请求,并发级别为 20。所以基本上我一次发出了 20 个请求。如您所见,大多数请求在很短的时间内执行,但有一两个请求需要很长时间。当我加载负载时,最长请求可以达到 3 秒,我见过的最高是 9!
我做了一些调试,发现问题出在接受代码上。我计算了从 process_sock 开始到结束需要多长时间,发现它从来没有变化,但是当我将计时器的开始移动到 gen_tcp:accept 之前,可以看到时间差。出于某种原因,接受不接受。我尝试增加最初生成的接受器的数量,并尝试不同的设计模式来生成 process_sock 工作人员,但没有任何改变。我应该注意,现在我从 50 个接受者开始,但在上面的 ab 输出中只有 20 个请求,所以我不认为工人数量是答案。
我正在运行 erlang R14B04,如果有帮助的话。
【问题讨论】: