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 错误