2012-04-09 8 views
10

Ich teste gerade extreme Bedingung auf ein Stück Code mit Erlang geschrieben.Erlang akzeptiert SSL-Verbindung ist wirklich langsam (im Vergleich zu C++)

Ich habe learnyousomeerlang.com Technik des Supervisor implementiert, um mehrere akzeptieren Fähigkeit.

Hier ist der Code leicht modifiziert, um SSL-Verbindungen des Betreuers zu behandeln:

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

Hier ist der Code für gen_server die jeden Client verbindet vertreten:

-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}}. 

[...] 

Ich habe die Fähigkeit der Nähe zu starten zu 10.000 Verbindungen gleichzeitig von mehreren Servern. Während es 10 Sekunden dauern wird, bis ein ssl akzeptierendes C++ - Bit akzeptiert, um alle zu akzeptieren (die noch nicht mehrere akzeptieren), ist das in Erlang ziemlich anders. Es akzeptiert maximal 20 Verbindungen pro Sekunde (nach netstat info, während C++ mehr wie 1K Verbindung pro Sekunde akzeptiert)

Während die 10K-Verbindungen auf Akzeptanz warten, versuche ich manuell zu verbinden.

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

3 Fälle passieren, wenn ich tun:

  • Verbindung einfach Timeout
  • Verbindung wird es 30 Sekunden nach einer Wartezeit verbinden. mindestens
  • Verbindung tritt fast direkt

Wenn ich versuche, manuell mit 2 Konsolen verbinden, wobei der erste getan Handshaking wird nicht immer die ersten sein, die ... zu verbinden versucht Was ich gefunden Besonderen.

Die Server-Konfiguration ist:

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

Ich fange der Erlang mit Shell:

$erl +S 8:8 

EDIT 1:

Ich habe sogar versucht, die Verbindung mit gen_tcp zu akzeptieren, und anschließend die Verbindung zu einem SSL-Upgrade. Immer noch das gleiche Problem, es wird nicht mehr als 10 Verbindungen pro Sekunde akzeptieren ... Ist ssl: ssl_accept dies tun? Sperrt alles, was Erlang daran hindern würde, das zu skalieren?

EDIT 2:

Nach etwas auf anderem SSL-Server in erlang erstellt, es scheint, dass sie irgendeine Art von Treiber für SSL/TLS-Verbindung verwenden, sind meine Beispiele RabbitMQ und ejabberd. Nirgends gibt es ssl_accept in ihrem Erlang-Code, ich habe nicht viel untersucht, aber es scheint, dass sie ihren eigenen Treiber erstellt haben, um den TCP-Socket zu einem SSL/TLS-Upgrade zu machen. Ist das, weil es ein Problem mit Erlangs Modul SSL gibt? Weiß jemand, warum sie benutzerdefinierten Treiber für SSL/TLS verwenden?

Irgendwelche Gedanken dazu?

+1

Ich schlage vor, diese Frage in der erlang Frage-Liste zu posten, um Antworten vom otp-Team zu erhalten (Ingela et al). – selle

+0

Ich habe das auch in Erwägung gezogen ... Allerdings kann jemand nicht auf Top-Team sein, habe die Antwort, oder zumindest einige führt ... – TheSquad

+0

Wenn Sie das OTP-Team direkt fragen, fragen Sie die Entwickler von RabbitMQ oder EjabberD. Sie sollten jetzt, warum sie dort entsprechende Lösungen gewählt haben! –

Antwort

7

Eigentlich war es nicht die SSL akzeptieren oder Handshake, die das Ganze verlangsamt wurde.

Wir fanden auf der Erlang-Frage-Liste, dass es der Rückstand war.

Backlog ist standardmäßig auf 5 gesetzt. Ich habe es auf SOMAXCONN eingestellt und alles funktioniert jetzt gut!

Verwandte Themen