私は入力ストリームを持っており、結果をプログラムの別の部分に渡す前に2 HTTPS
それぞれのネットワーク要求を作りたいと思います。一般的なスループットは50 /秒です。Clojure(/ Java)で多くの同時HTTPS要求を強く行うには
for each input:
HTTP request A
HTTP request B
pass event on with (A.body and B.body)
私は、デフォルトでは非同期ですhttp-kit
クライアントを、使用しています。それは約束を返し、またコールバックを取ることができます。 Http-kitはJava NIOを使用します(hereとhere)
要求の到着速度と要求を行う時間は、非同期で行う必要があるほど十分です。イベントが来ると
- は、チャネルの上に置く:
私は3つのアプローチを試みました。多数の
go
ルーチンがチャネルを抜け出しています。各メイクは、HTTPリクエストから約束を受けてゴブロックをブロックするように要求しています。私は約束がスレッドでうまくいくとは思わないので、これはうまくいかない。 - イベントが到着したらすぐに
future
を開始します。これは非同期の約束を「ブロック」します。これにより、が非常にとCPU使用率が高くなります。何とかネットワーク資源の枯渇。 - イベントが到着したら、リクエストAを即座に起動し、リクエストBをコールバックしてイベントを渡すコールバックを渡します。これにより、数時間後にメモリ不足エラーが発生します。
これらはすべて機能し、しばらくの間容量を処理します。彼らはすべて最終的にクラッシュする。最新の約12時間後のクラッシュ:
Mar 10, 2016 2:05:59 AM com.mchange.v2.async.ThreadPoolAsynchronousRunner$DeadlockDetector run
WARNING: com[email protected]1bc8a7f5 -- APPARENT DEADLOCK!!! Creating emergency threads for unassigned pending
tasks!
Mar 10, 2016 3:38:38 AM com.mchange.v2.async.ThreadPoolAsynchronousRunner$DeadlockDetector run
WARNING: com[email protected]1bc8a7f5 -- APPARENT DEADLOCK!!! Complete Status:
Managed Threads: 3
Active Threads: 1
Active Tasks:
com[email protected]65d8b232 (com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread-#0)
Pending Tasks:
[email protected]0d
Pool thread stack traces:
Thread[com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread-#0,5,main]
com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread.run(ThreadPoolAsynchronousRunner.java:560)
Thread[com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread-#1,5,main]
java.lang.Object.wait(Native Method)
com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread.run(ThreadPoolAsynchronousRunner.java:534)
Thread[com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread-#2,5,main]
java.lang.Object.wait(Native Method)
com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread.run(ThreadPoolAsynchronousRunner.java:534)
Thu Mar 10 04:38:34 UTC 2016 [client-loop] ERROR - select exception, should not happen
java.lang.OutOfMemoryError: Java heap space
at java.io.ByteArrayOutputStream.<init>(ByteArrayOutputStream.java:77)
at sun.security.ssl.OutputRecord.<init>(OutputRecord.java:76)
at sun.security.ssl.EngineOutputRecord.<init>(EngineOutputRecord.java:65)
at sun.security.ssl.HandshakeOutStream.<init>(HandshakeOutStream.java:63)
at sun.security.ssl.Handshaker.activate(Handshaker.java:514)
at sun.security.ssl.SSLEngineImpl.kickstartHandshake(SSLEngineImpl.java:717)
at sun.security.ssl.SSLEngineImpl.beginHandshake(SSLEngineImpl.java:743)
at org.httpkit.client.HttpClient.finishConnect(HttpClient.java:310)
at org.httpkit.client.HttpClient.run(HttpClient.java:375)
at java.lang.Thread.run(Thread.java:745)
Mar 10, 2016 4:56:34 AM baleen.events invoke
SEVERE: Thread error: Java heap space
java.lang.OutOfMemoryError: Java heap space
Mar 10, 2016 5:00:43 AM baleen.events invoke
SEVERE: Thread error: Java heap space
java.lang.OutOfMemoryError: Java heap space
Mar 10, 2016 4:58:25 AM baleen.events invoke
SEVERE: Thread error: Java heap space
java.lang.OutOfMemoryError: Java heap space
私は障害の原因がわかりません。閉鎖があまりにも多く、または徐々にリソースが漏れているか、スレッドが枯渇している可能性があります。
質問
過度の負担のように、任意の時点で飛行中の100個の要求があるかもしれないと音を意味し、それぞれが200msのを取るかもしれませんが、毎秒50件のHTTPリクエストを作成していますか?
スループットを処理して堅牢な方法でこれを行うにはどうすればよいですか?
EDIT
YourKitプロファイラは、私は古いハンドラ(つまり要求)への参照が何らかの形で保持されていることを示唆しているjava.util.concurrent.FutureTask
Sを経由してorg.httpkit.client.Handler
秒経由char[]
の約2GBの持っていることを私に伝えます。コールバックを使用しようとする全理由は、これを避けることでした(閉鎖時に何らかの形で巻き込まれる可能性がありますが)。
OutOfMemoryErrorは、メモリの保持に問題があることを示していますが、コードを表示したり、完全な解決策を最初から作成したりすることはできません。私は、無限のシーケンスの先頭をつかむか、コネクションなどのリソースをクリーンアップしないかを探します。 –
バッファが保持されているかどうかは分かりましたが、ガベージコレクションで解放メモリ/外部バッファを処理する必要があることがわかります。 NIOは割り当てていた。ダウンストリームで起こるのは、ちょうどデータベース挿入とチャンネルへの挿入です。 – Joe
私はコードを投稿することを考えましたが、それはかなり複雑で、単純化したバージョンで問題を再現するかどうかを知るのに1日ほどかかります。 – Joe