HTTPS
入力ストリームがあり、結果をプログラムの別の部分に渡す前に、それぞれに対して 2 つのネットワーク要求を作成したいと考えています。通常のスループットは 1 秒あたり 50 です。
for each input:
HTTP request A
HTTP request B
pass event on with (A.body and B.body)
http-kit
デフォルトで非同期のクライアントを使用しています。プロミスを返し、コールバックを取ることもできます。Http-kit は Java NIO を使用します (こちらとこちらを参照)
受信するリクエストの速度は、リクエストを作成する時間と合わせて十分に高速であるため、これを非同期で行う必要があります。
私は3つのアプローチを試しました:
- イベントが発生したら、チャネルに配置します。
go
チャネルを引き離す多くのルーチン。deref
それぞれが、HTTP リクエストから promise を ing することにより、goblock を「ブロック」するリクエストを作成します。約束がスレッドでうまく機能するとは思わないため、これは機能しません。 - イベントが発生すると、すぐ
future
に async promise を「ブロック」する を開始します。これにより、CPU 使用率が非常に高くなります。さらに、何らかの形でネットワーク リソースが枯渇します。 - イベントが発生すると、
http-kit
リクエスト A のリクエストをすぐにトリガーし、リクエスト B を作成するコールバックを渡し、イベントを渡すコールバックを渡します。これにより、数時間後にメモリ不足エラーが発生します。
これらはすべて機能し、しばらくの間容量を処理します。それらはすべて最終的にクラッシュします。約 12 時間後の最新のクラッシュ:
Mar 10, 2016 2:05:59 AM com.mchange.v2.async.ThreadPoolAsynchronousRunner$DeadlockDetector run
WARNING: com.mchange.v2.async.ThreadPoolAsynchronousRunner$DeadlockDetector@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.mchange.v2.async.ThreadPoolAsynchronousRunner$DeadlockDetector@1bc8a7f5 -- APPARENT DEADLOCK!!! Complete Status:
Managed Threads: 3
Active Threads: 1
Active Tasks:
com.mchange.v2.resourcepool.BasicResourcePool$1DestroyResourceTask@65d8b232 (com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread-#0)
Pending Tasks:
com.mchange.v2.resourcepool.BasicResourcePool$AcquireTask@359acb0d
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
失敗の原因はわかりません。保持されているクロージャが多すぎるか、段階的なリソースのリーク、またはスレッドの枯渇が発生している可能性があります。
質問
1 秒あたり 50 件の HTTP リクエストを作成し、それぞれに 200 ミリ秒かかる場合があります。つまり、常に 100 件のリクエストが処理中である可能性があるということは、過度の負担に思えますか?
スループットを処理し、堅牢な方法でこれを行うにはどうすればよいですか?
編集
char[]
YourKit プロファイラーは、約 2GB のs via org.httpkit.client.Handler
s via s があることを教えてくれます。java.util.concurrent.FutureTask
これは、古いハンドラー (つまり、要求) への参照が何らかの形で保持されていることを示唆しています。コールバックを使用しようとする全体的な理由は、これを回避することでした (ただし、何らかの形でクロージャーに巻き込まれる可能性があります)。