2012-04-09 3 views
10

В настоящее время я тестирую экстремальное состояние на фрагменте кода, написанном с помощью Erlang.Erlang, принимающий SSL-соединение, очень медленный (по сравнению с C++)

Я реализовал технику супервайзера 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 соединений сразу с нескольких серверов. В то время как для принятия всех из них (которые даже не имеют многократного приема), в Erlang это займет 10 секунд, чтобы принять бит Csl, чтобы принять все это, это совсем другое. Он будет принимать не более 20 подключений в секунду (в соответствии с информацией netstat, в то время как C++ принимает больше, чем 1K-соединение в секундах)

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

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

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

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

При попытке подключения вручную с помощью 2-х консолей, то первый сделал рукопожатия не всегда быть первым, который пытался соединить ... Который я нашел частности.

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

  • 2 х Intel® Xeon® E5620
  • 8x 2,4
  • 24 Перейти ОЗУ

Я начал Эрланг оболочки с:

$erl +S 8:8 

EDIT 1:

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

EDIT 2:

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

Любые мысли по этому поводу?

+1

Я предлагаю отправить этот вопрос в список вопросов erlang, чтобы получить ответы от команды otp (Ingela et al). – selle

+0

Я тоже подумал, что ... Но может быть кто-то не в верхней команде, у меня есть ответ, или, по крайней мере, некоторые лидеры ... – TheSquad

+0

Если вам неловко задавать команду OTP напрямую, попробуйте спросить разработчиков RabbitMQ или EjabberD. Теперь они должны понять, почему они выбрали соответствующие решения! –

ответ

7

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

Мы обнаружили в списке вопросов erlang, что это был накопительный период.

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