Erlang 接受 SSL 连接真的很慢(与 C++ 相比)

Posted

技术标签:

【中文标题】Erlang 接受 SSL 连接真的很慢(与 C++ 相比)【英文标题】:Erlang accepting SSL connection is really slow (comparing to C++) 【发布时间】:2012-04-22 01:34:40 【问题描述】:

我目前正在用 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, []).

这是 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, #clientsocket=Socket, pid=self().

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

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

[...]

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

当 10K 连接等待接受时,我也在手动尝试连接。

openssl s_client -ssl3 -ign_eof -connect myserver.com:4242

当我这样做时会发生 3 种情况:

连接只是超时 连接将在等待 30 秒后连接。至少 几乎直接建立连接

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

服务器配置为:

2 个英特尔® 至强® E5620 8x 2.4GHz 24 转内存

我正在启动 Erlang shell:

$erl +S 8:8

编辑 1:

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

编辑 2:

查看其他用 erlang 创建的 SSL 服务器后,似乎他们使用某种驱动程序进行 SSL/TLS 连接,我的例子是 RabbitMQ 和 EjabberD。 他们的 Erlang 代码中没有 ssl:ssl_accept,我没有进行太多调查,但似乎他们已经创建了自己的驱动程序以将 TCP 套接字升级到 SSL/TLS 驱动程序。 那是因为 Erlang 的模块 SSL 有问题吗?有谁知道他们为什么要为 SSL/TLS 使用自定义驱动程序?

对此有什么想法吗?

【问题讨论】:

我建议将此问题发布到 erlang 问题列表中,以便从 otp 团队(Ingela 等人)那里获得答案。 我也考虑过......但是可能不是***团队的人我有答案,或者至少有一些线索...... 如果您不方便直接询问 OTP 团队,请尝试询问 RabbitMQ 或 EjabberD 的开发人员。他们现在应该为什么他们选择了各自的解决方案! @EmilVikström:实际上我刚刚在 erlang 问题列表中提出了我的问题,还没有 OTP 团队回答。但我们正在努力。如果有有趣的事情发生,我当然会更新我的帖子。 @EmilVikström :根据 OTP 团队的 Ingela 的说法,他们已经这样做了,因为以前版本的 OTP(创建项目时)不支持 SSL/TLS 连接升级。 【参考方案1】:

实际上,减缓整个过程的并不是 SSL 接受或握手。

我们在 erlang 问题列表中发现它是 backlog。

默认情况下,积压设置为 5。我已将其设置为 SOMAXCONN,现在一切正常!

【讨论】:

以上是关于Erlang 接受 SSL 连接真的很慢(与 C++ 相比)的主要内容,如果未能解决你的问题,请参考以下文章

使用 SSL 与远程数据库的 PDO 连接;验证服务器证书时出现 FastCGI 错误

配置 Erlang 以使用 SSL

在 Erlang 中通过 RPC 在远程节点上创建套接字时,无法接受套接字上的连接

Erlang 中的接受器池和负载平衡?

C ++中的异常真的很慢吗

接受 websocket 使用 tcp .net 很慢?