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, []).

Вот код для 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}}.

[...]

У меня есть возможность запускать сразу около 10.000 соединений с нескольких серверов. Хотя для принятия всех из них (которые даже не имеют нескольких ожидающих приема) потребуется около 10 секунд для принимающего ssl бит кода С++, в Erlang это совсем другое. Он будет принимать не более 20 подключений в секунду (согласно информации netstat, в то время как С++ принимает больше как 1K-соединение в секунду)

Пока соединения 10K ждут подтверждения, я также вручную пытаюсь подключиться.

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

3 случая случаются, когда я делаю:

  • Соединение просто с тайм-аутом
  • Соединение будет подключаться после ожидания 30 секунд. по крайней мере
  • Соединение произойдет почти напрямую.

Когда я пытаюсь подключиться вручную с двумя консолями, первое сделанное квитирование не всегда будет первым, которое пыталось подключиться... Что я нашел особенно.

Конфигурация сервера:

  • 2 x Intel® Xeon® E5620
  • 8x 2,4 ГГц
  • 24 Go RAM

Я запускаю оболочку Erlang с помощью:

$erl +S 8:8

РЕДАКТИРОВАТЬ 1:

Я даже попытался принять соединение с gen_tcp и впоследствии обновить соединение с SSL. Еще одна проблема, она не будет принимать более 10 подключений в секунду... Является ли ssl: ssl_accept? блокирует ли это что-либо, что помешало бы Erlang масштабировать это?

ИЗМЕНИТЬ 2:

Посмотрев на другой сервер SSL, созданный в erlang, кажется, что они используют какой-то драйвер для соединения SSL/TLS, моими примерами являются RabbitMQ и EjabberD. Нигде нет ssl: ssl_accept в их коде Erlang, я не много разбираюсь, но, похоже, они создали свой собственный драйвер, чтобы обновить TCP Socket до SSL/TLS. Это потому, что есть проблема с модулем SSL Erlang? Кто-нибудь знает, почему они используют собственный драйвер для SSL/TLS?

Любые мысли об этом?

Ответ 1

На самом деле это было не одобрение SSL или рукопожатие, которое замедляло все это.

Мы нашли в списке вопросов erlang, что это было отставание.

По умолчанию для отставания установлено значение 5. Я установил его в SOMAXCONN, и теперь все работает отлично!