代码之家  ›  专栏  ›  技术社区  ›  Jan Deinhard

为什么当我的erlangtcp代理得到许多并发请求时性能会下降这么多?

  •  4
  • Jan Deinhard  · 技术社区  · 16 年前

    为了便于学习,我用Erlang编写了一个简单的TCP代理。它可以工作,但当我使用ab(apachebench)发出许多并发请求时,我遇到了一个奇怪的性能下降。我想知道的不是性能下降本身,而是下降的幅度。后端是nginx作为web服务器。我的代理人在ab和nginx之间。

    这是我代理人的密码。

    -module(proxy).
    -export([start/3]).
    
    start(InPort, OutHost, OutPort) ->
      {ok, Listen} = gen_tcp:listen(InPort, [binary, {packet, 0}, {active, once}]),
      spawn(fun() -> connect(Listen, OutHost, OutPort) end).
    
    connect(Listen, OutHost, OutPort) ->
      {ok, Client} = gen_tcp:accept(Listen),
      spawn(fun() -> connect(Listen, OutHost, OutPort) end),
      {ok, Server} = gen_tcp:connect(OutHost, OutPort, [binary, {packet, 0}, {active, once}]),
      loop(Client, Server).
    
    loop(Client, Server) ->
      receive
        {tcp, Client, Data} ->
          gen_tcp:send(Server, Data),
          inet:setopts(Client, [{active, once}]),
          loop(Client, Server);
        {tcp, Server, Data} ->
          gen_tcp:send(Client, Data),
          inet:setopts(Server, [{active, once}]),
          loop(Client, Server);
        {tcp_closed, _} ->
          ok
      end.
    

    在我的代理上触发64个连续的请求,我得到了一个非常好的结果。

    ab -n 64 127.0.0.1:80/
    
    Concurrency Level:      1
    Time taken for tests:   0.097 seconds
    Complete requests:      64
    Failed requests:        0
    Write errors:           0
    Total transferred:      23168 bytes
    HTML transferred:       9664 bytes
    Requests per second:    659.79 [#/sec] (mean)
    Time per request:       1.516 [ms] (mean)
    Time per request:       1.516 [ms] (mean, across all concurrent requests)
    Transfer rate:          233.25 [Kbytes/sec] received
    
    Connection Times (ms)
                  min  mean[+/-sd] median   max
    Connect:        0    0   0.3      0       1
    Processing:     1    1   0.5      1       2
    Waiting:        0    1   0.4      1       2
    Total:          1    1   0.5      1       2
    
    Percentage of the requests served within a certain time (ms)
      50%      1
      66%      2
      75%      2
      80%      2
      90%      2
      95%      2
      98%      2
      99%      2
     100%      2 (longest request)
    

    它只是比直接对nginx使用apachebench慢一点。

    ab -n 64 -c 64 127.0.0.1:80/
    
    Concurrency Level:      64
    Time taken for tests:   2.011 seconds
    Complete requests:      64
    Failed requests:        0
    Write errors:           0
    Total transferred:      23168 bytes
    HTML transferred:       9664 bytes
    Requests per second:    31.82 [#/sec] (mean)
    Time per request:       2011.000 [ms] (mean)
    Time per request:       31.422 [ms] (mean, across all concurrent requests)
    Transfer rate:          11.25 [Kbytes/sec] received
    
    Connection Times (ms)
                  min  mean[+/-sd] median   max
    Connect:        0   31 121.7      0     501
    Processing:     3 1135 714.4   1001    2006
    Waiting:        3 1134 714.3   1000    2005
    Total:          3 1167 707.8   1001    2006
    
    Percentage of the requests served within a certain time (ms)
      50%   1001
      66%   1502
      75%   2003
      80%   2004
      90%   2005
      95%   2005
      98%   2005
      99%   2006
     100%   2006 (longest request)
    

    问题出在哪里?我本以为会有更低的表现,但为什么会有这么多呢?看看每秒的请求数!

    我是否使用+a给erl提供了很多线程似乎无关紧要。我甚至尝试了SMP,但结果几乎相同。

    我的设置:Windows764,英特尔四核,8GB内存。我在Ubuntu上使用128个并发请求得到了类似的结果。

    编辑:包括新见解。请求的总数并不重要。这只是并发请求的计数。

    4 回复  |  直到 15 年前
        1
  •  5
  •   Hynek -Pichi- Vychodil Paulo Suassuna    16 年前

    这部分 connect/3

    connect(Listen, OutHost, OutPort) ->
      {ok, Client} = gen_tcp:accept(Listen),
      spawn(fun() -> connect(Listen, OutHost, OutPort) end),
    

    gen_tcp:accept/1 准备好了。它可能涉及到代码的瓶颈。在这种情况下,您可以尝试使用“接受者”池来提高性能。我也会尝试将catch all子句添加到 loop/2 receive 以避免意外地塞满邮箱。

    erl +A 线程 +K true

        2
  •  1
  •   Javier    16 年前

        3
  •  1
  •   klm    16 年前

    我无法复制你的结果。我尝试了使用apache、yaws和nginx作为web服务器的测试,发现在使用代理和不使用代理的情况下,它们运行的变化都很小。我确实在Linux上运行过它们,所以可能是Windows或Windows版本的erlang VM有问题。

        4
  •  1
  •   wchargin Frank    14 年前

    {backlog, B} gen_tcp:listen ?