2012-04-09 9 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では、(複数の受け入れ待ちをしていなくても)すべてを受け入れるために、C++コードのssl受け入れビットに10秒かかりますが、これは全く異なります。最大20個の接続を1秒間で受け付けます(netstat情報によると、C++は1秒あたりの1K接続のように受け入れます)

10K接続が受け入れられるのを待っていますが、手動で接続しようとしています。単にタイムアウト

  • 接続はそれのために30秒待ってから接続します

    • 接続:

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

      3例は私が行うときに起こります。少なくとも

    • 接続が発生しますほとんど直接

    私は2つのコンソールを使って手動で接続しようとすると、最初に行われ、常に私は特定の見つけた...接続しようとした最初ではありませんハンドシェーク。

    サーバー構成は次のとおりです。

    • 2×インテル®Xeon®E5620
    • 8倍の2.4GHz
    • 24ゴーRAM

    私はErlangのシェルを起動しています:

    $erl +S 8:8 
    

    EDIT 1:

    私はgen_tcpとの接続を受け入れ、その後SSL接続への接続をアップグレードしようとしました。それでも、同じ問題ですが、10秒以上の接続は受け付けません... ssl:ssl_acceptはこれをやっていますか? Erlangがこれをスケールするのを妨げる何かをロックしていますか?

    EDIT 2:

    Erlangで作成された他のSSLサーバ上で周りを探した後、彼らがSSL/TLS接続用のドライバのいくつかの種類を使用することを、私の例では、RabbitMQのとEjabberDあるようです。 Erlangコードにはssl:ssl_acceptがありませんが、私はまだ調査していませんが、TCPソケットをSSL/TLSにアップグレードするために独自のドライバを作成したようです。 ErlangのモジュールSSLに問題があるためですか? SSL/TLS用のカスタムドライバを使用している理由を知っていますか?

    これについてのご意見はありますか?

  • +1

    otp-team(Ingela et al)の回答を得るために、この質問をerlang質問リストに掲載することをお勧めします。 – selle

    +0

    私もそれを考慮しています...しかし、トップのチームにいない人が私の答えを持っているか、少なくともいくつかのリードが... – TheSquad

    +0

    OTPチームに直接質問するのが不快なら、RabbitMQまたはEjabberDの開発者に尋ねてみてください。彼らは今、それぞれのソリューションを選んだのはなぜだろう! –

    答えて

    7

    実際には、全体を遅くしていたのはSSLの受け入れやハンドシェイクではありませんでした。

    erlangの質問リストで、バックログであることがわかりました。

    デフォルトでは、バックログは5に設定されています。私はSOMAXCONNに設定して、今はすべて正常に動作します!

    関連する問題