Erlang接受SSL连接的速度非常慢(与C++相比)

The*_*uad 10 sockets erlang ssl

我目前正在使用Erlang编写的一段代码测试极端条件.

我已经实现了learnyousomeerlang.com的主管技术,具有多种接受能力.

这里稍微修改了代码以处理主管的SSL连接:

-module(mymodule).

-behaviour(supervisor).

-export([start/0, start_socket/0]).
-define(SSL_OPTIONS, [{active, true},
              {mode, list},
              {reuseaddr, true},
              {cacertfile, "./ssl_key/server/gd_bundle.crt"},
              {certfile, "./ssl_key/server/cert.pem"},
              {keyfile, "./ssl_key/server/key.pem"},
              {password, "********"}
             ]).

-export([init/1]).

start_link() ->
    application:start(crypto),
    crypto:start(),
    application:start(public_key),
    application:start(ssl),
    supervisor:start_link({local, ?MODULE}, ?MODULE, []).

init([]) ->
    {ok, LSocket} = ssl:listen(4242, ?SSL_OPTIONS),
    spawn_link(fun empty_listeners/0),
    {ok, {{simple_one_for_one, 60, 3600},
      [{socket,
        {mymodule_serv, start_link, [LSocket]}, % pass the socket!
        temporary, 1000, worker, [mymodule_serv]}
      ]}}.

empty_listeners() ->
    [start_socket() || _ <- lists:seq(1,100)],
    ok.

start_socket() ->
    supervisor:start_child(?MODULE, []).
Run Code Online (Sandbox Code Playgroud)

这是gen_server的代码,它代表每个连接的客户端:

-module(mymodule_serv).
-behaviour(gen_server).

-export([start_link/1]).
-export([init/1, handle_call/3, handle_cast/2, terminate/2, code_change/3, handle_info/2]).

start_link(Socket) ->
    gen_server:start_link(?MODULE, Socket, []).

init(Socket) ->
    gen_server:cast(self(), accept),
    {ok, #client{socket=Socket, pid=self()}}.

handle_call(_E, _From, Client) ->
    {noreply, Client}.

handle_cast(accept, C = #client{socket=ListenSocket}) ->
    {ok, AcceptSocket} = ssl:transport_accept(ListenSocket),
    mymodule:start_socket(),
    ssl:ssl_accept(AcceptSocket),
    ssl:setopts(AcceptSocket, [{active, true}, {mode, list}]),
    {noreply, C#client{socket=AcceptSocket, state=connecting}}.

[...]
Run Code Online (Sandbox Code Playgroud)

我能够从多个服务器一次启动接近10.000个连接.虽然接受C++代码的ssl需要10秒才能接受所有这些代码(它们甚至没有多个接受暂挂),但在Erlang中这是完全不同的.它每秒最多可接受20个连接(根据netstat信息,而C++接受更多像每秒1K连接)

虽然10K连接正在等待接受,但我也在手动尝试连接.

openssl s_client -ssl3 -ign_eof -connect myserver.com:4242
Run Code Online (Sandbox Code Playgroud)

我做的时候会发生3例:

  • 连接只是超时
  • 等待30秒后连接将连接.至少
  • 连接几乎直接发生

当我尝试用2个控制台手动连接时,第一次完成握手并不总是第一次试图连接...我发现特别的.

服务器配置是:

  • 2个Intel®Xeon®E5620
  • 8x 2.4GHz
  • 24去RAM

我正在启动Erlang shell:

$erl +S 8:8
Run Code Online (Sandbox Code Playgroud)

编辑1:

我甚至尝试接受与gen_tcp的连接,然后升级到SSL连接.仍然是同样的问题,它不会接受每秒超过10个连接... ssl:ssl_accept是这样做的吗?它会阻止任何阻止Erlang扩展的东西吗?

编辑2:

在浏览了在erlang中创建的其他SSL服务器之后,似乎他们使用某种驱动程序进行SSL/TLS连接,我的示例是RabbitMQ和EjabberD.在他们的Erlang代码中没有ssl:ssl_accept,我没有进行过多次调查,但似乎他们已经创建了自己的驱动程序,以便将TCP Socket升级为SSL/TLS.这是因为Erlang的模块SSL存在问题吗?有谁知道为什么他们使用SSL/TLS的自定义驱动程序?

有什么想法吗?

The*_*uad 7

实际上,SSL接受或握手并不会减慢整个过程.

我们在erlang问题列表中发现它是积压的.

Backlog默认设置为5.我把它设置为SOMAXCONN,现在一切正常!