12

私のアプリケーションは 10 近くのスレッドを使用しており、それぞれが 1 分あたりおそらく 7,000 の Put リクエストを S3 に送信します。(負荷をうまく処理できる強力な EC2 ボックスで実行しています。) 1 時間近くは問題なく動作しますが、1 時間後にUnable to execute HTTP request: Socket Closed例外が発生します。

        http.AmazonHttpClient: Unable to execute HTTP request: Socket Closed
    java.net.SocketException: Socket Closed
    at java.net.AbstractPlainSocketImpl.setOption(AbstractPlainSocketImpl.java:206)
    at java.net.Socket.setSoTimeout(Socket.java:1105)
    at sun.security.ssl.SSLSocketImpl.setSoTimeout(SSLSocketImpl.java:2414)
    at org.apache.http.impl.io.SocketInputBuffer.isDataAvailable(SocketInputBuffer.java:106)
    at org.apache.http.impl.AbstractHttpClientConnection.isResponseAvailable(AbstractHttpClientConnection.java:246)
    at org.apache.http.impl.conn.ManagedClientConnectionImpl.isResponseAvailable(ManagedClientConnectionImpl.java:180)
    at org.apache.http.protocol.HttpRequestExecutor.doSendRequest(HttpRequestExecutor.java:238)
    at com.amazonaws.http.protocol.SdkHttpRequestExecutor.doSendRequest(SdkHttpRequestExecutor.java:47)
    at org.apache.http.protocol.HttpRequestExecutor.execute(HttpRequestExecutor.java:125)
    at org.apache.http.impl.client.DefaultRequestDirector.tryExecute(DefaultRequestDirector.java:713)
    at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:518)
    at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:906)
    at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:805)
    at com.amazonaws.http.AmazonHttpClient.executeHelper(AmazonHttpClient.java:446)
    at com.amazonaws.http.AmazonHttpClient.execute(AmazonHttpClient.java:256)
    at com.amazonaws.services.s3.AmazonS3Client.invoke(AmazonS3Client.java:3641)
    at com.amazonaws.services.s3.AmazonS3Client.putObject(AmazonS3Client.java:1438)
    at com.amazonaws.services.s3.transfer.internal.UploadCallable.uploadInOneChunk(UploadCallable.java:128)
    at com.amazonaws.services.s3.transfer.internal.UploadCallable.call(UploadCallable.java:120)
    at com.amazonaws.services.s3.transfer.internal.UploadMonitor.upload(UploadMonitor.java:176)
    at com.amazonaws.services.s3.transfer.internal.UploadMonitor.call(UploadMonitor.java:134)
    at com.amazonaws.services.s3.transfer.internal.UploadMonitor.call(UploadMonitor.java:50)
    at java.util.concurrent.FutureTask.run(FutureTask.java:262)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)

Put リクエストは、AWS SDK TransferManager を使用して非同期で行われます。1 つの put リクエストが完全に完了するまでに、約 10 件の put リクエストが非同期で行われたと思います。

その例外をグーグルで調べたところ、考えられる原因が2つ見つかりました。

  1. MaxConnections の制限。デフォルトの 50 から 3000 に上げましたが、役に立ちませんでした。
  2. 時期尚早のガベージ コレクション。TransferManager によって返されたオブジェクトへの参照を (同時キューで) 保持しようとしましたがUpload、やはり助けにはなりません。

どうすればこれを修正できますか? 繰り返しになりますが、アプリは 1 時間近く正常に動作しますが、一貫して、約 1 時間後にこの壁にぶつかります。(EC2 上の Amazon AMI Linux で実行しています。)

アップデート

  • AWS SDK 以外のコードは、ソケットに触れたり、ソケットについて認識したりすることさえありません。すべての HTTP 作業は、AWS SDK を介してのみ行われます。
  • したがって、何かがそれらを閉じている場合、それは AWS SDK の何かである必要があります。
  • コードは EC2 サーバーで実行されています。EC2 と S3 の間で何らかのネットワーク接続の問題が発生することを予期する理由はありません。
4

4 に答える 4

1

これが答えかどうかはわかりませんが、http://docs.aws.amazon.com/AmazonS3/latest/dev/request-rate-perf-considerations.htmlには、「 1 秒あたり 300 を超える PUT/LIST/DELETE リクエストまたは 1 秒あたり 800 を超える GET リクエストに対するバケットのリクエスト レートが必要な場合は、サポート ケースを開いてワークロードに備え、リクエスト レートの一時的な制限を回避することをお勧めします。おそらく制限を超えたために、AWS は接続を中止し始めます。SDK は、IDLE ソケットを検出してそれらを閉じます。すると、ほら、例外が発生します。

更新:これが正しいかどうかはわかりません。Amazon は、この場合、予期しない終了ではなく、明示的な「Slow Down」エラー メッセージが表示されると述べているようです。というわけで、謎は残ります。

于 2014-10-03T01:14:45.547 に答える
1

例外は、java.net.Socket の setSoTimeout() メソッドによる SocketException です (スタック トレースを参照)。メソッドはここで見ることができます: http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/net/Socket.java#Socket.setSoTimeout%28int%29

考えられる理由としては、S3 へのリクエストがまだ保留中または未完了であるため、スレッドが wait() になっている可能性があります。待機時間が socket timeout を超えると、ソケットが閉じられ、例外がスローされます。

于 2014-10-07T06:05:44.183 に答える
-1

を試したほうがいいと思いますClientConfiguration.setSocketTimeout(int)。ソケットが非同期で閉じられている場合は、タイムアウトが原因だと思います。アマゾンのドキュメントによると:

public void setSocketTimeout(int socketTimeout)

Sets the amount of time to wait (in milliseconds) for data to be transfered 
over an established, open connection before the connection times out and is closed. 
A value of 0 means infinity, and isn't recommended.

ということで、ドキュメントによると、接続がタイムアウトした場合、自動的に閉じられると思います。

リンク: http://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/ClientConfiguration.html#setSocketTimeout(int)

于 2014-10-01T08:54:26.507 に答える
-3

この例外の原因は 1 つだけです。あなたまたはあなたのフレームワークがソケットを閉じてから、それを使い続けました。

于 2014-09-24T20:41:36.043 に答える