2017-08-20 9 views
2

編集:この問題は、SSLアクセラレーションとメモリリークの問題であるようです。あなたが長い(そのサーバー)プロセスを生きてきた、そしてクライアントがサーバ(RECV)にデータを送信する場合Erlang SSL TCPサーバーとガベージコレクション

は私が気づいた、Erlangのガベージコレクションは

サーバーがに(データを必要と呼ばれていない(またはめったに)を取得しませんプリフォームアクション)、データは可変長でもかまいません(「こんにちは」や「やっていますか?」などのメッセージが原因です)。このため、Erlangプロセスではゴミが蓄積されるようです。

これを適切に処理するには、Erlangプロセスがrecvデータに触れなければならないのですが、どうしてですか?あるいは、可変長データに触れるデザインを(ポートドライバに直ちに渡すような)より少ない時間で実現する必要があります。

データを処理するワーカーを作成することは悪い解決策です(何百万という接続)...そして、従業員を使用するのは基本的に同じでしょうか?だから私にはほとんどオプションがありません。サーバはそれが必要以上に長く、受信したメッセージに上保持している場合

おかげで...

+1

、私はhttps://hamidreza-s.github.io/erlang%20garbage%20collection%20memory%20layout%20soft%20realtime/2015/08/24/を読むことをお勧めしますerlang-garbage-collection-details-and-why-it-matters.html – Pouriya

答えて

0

誰もが同じボートで自分自身を見つけることができます。これは、一度に多くの接続でサーバーを叩くと知られています。おもう。

sslがないと、私のセッションは約8KBになり、リソースはGCのために期待どおりトリガーされています。 SSLを使用すると、〜150KBまで増加し、メモリは成長を続け、成長し、成長し続けます。

http://erlang.org/pipermail/erlang-questions/2017-August/093037.html

+0

erlang:garbage_collect/0/1/2を呼び出してGCを強制的に試行できます。 http://erlang.org/doc/man/erlang.html#garbage_collect-0を参照してください。各リクエストの後にGC:ingが動作する場合は、n回目のリクエストごとにそれを切り捨てて、nに適した値を見つけてください。 – RichardC

+0

問題が解決したかどうかは分かりませんが、SSLを使用しているすべての修正でも、ユーザープロセスは142 + KB(論理なし、ssl:recvのみ)増加します。これは受け入れがたい。私の最終的な解決策は、SRPログイン資格情報だけで、データのために何らかのタイプの暗号化(多分AES)を可能にすることです。 – Mike5050

3

は、それがサーバーの実装のバグです。通常、サーバーは、要求の処理が終了した時点で、要求内のデータのすべてまたはほとんどの参照を忘れてしまい、データがガベージになり、最終的に収集されます。しかし、各リクエストのデータをプロセス状態のリスト、またはetsテーブルなどに張り付けると、メモリリークが発生します。

参照カウントによって処理されるため、64バイトを超えるバイナリでは例外が少しあります。また、メモリアロケータには、コレクションをまだ実行する必要がないように見えますが、使用されるバイト数そのようなバイナリによるオフ・ヒープはかなり大きくなる可能性があります。

0

あなたは大規模なSSL/TLSセッションテーブルに問題がある可能性があります。私たち(OTPチーム)は歴史的にいくつかの問題を抱えていました。なぜなら、あなたには何らかの制限メカニズムがないと、非常に大きくなるかもしれないからです。最新のsslバージョンでは、制限メカニズムの1つが壊れていましたが、このパッチでは簡単に修正されています。回避策として、効率を犠牲にしてセッションの再利用を無効にすることもできます。あなたはアーランGCの詳細が必要

diff --git a/lib/ssl/src/ssl_manager.erl b/lib/ssl/src/ssl_manager.erl 
index ca9aaf4..ef7c3de 100644 
--- a/lib/ssl/src/ssl_manager.erl 
+++ b/lib/ssl/src/ssl_manager.erl 
@@ -563,7 +563,7 @@ server_register_session(Port, Session, #state{session_cache_server_max = Max, 

do_register_session(Key, Session, Max, Pid, Cache, CacheCb) -> 
    try CacheCb:size(Cache) of 
- Max -> 
+ Size when Size >= Max -> 
    invalidate_session_cache(Pid, CacheCb, Cache); 
_ ->  
    CacheCb:update(Cache, Key, Session), 
関連する問題