12

我的应用程序使用近 10 个线程,每个线程每分钟向 S3 发出大约 7,000 个 Put 请求。(我在一个功能强大的 EC2 机器上运行它,它可以很好地处理负载。)它运行得很漂亮将近一个小时,但是,一个小时后,出现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)

使用 AWS 开发工具包 TransferManager 异步完成放置请求。我想,在一个 put 请求完全完成所需的时间内,大约有 10 个是异步的。

谷歌搜索该异常,我发现了两个可能的原因:

  1. MaxConnections 的限制。我已将其从默认的 50 提高到 3000,但无济于事。
  2. 过早的垃圾收集。我尝试保留对UploadTransferManager 返回的对象的引用(在并发队列中),但同样没有帮助。

我怎样才能解决这个问题?同样,该应用程序运行良好近一个小时,但始终如一地在大约一个小时后撞到这堵墙。(我在 EC2 上的 Amazon AMI Linux 上运行。)

更新

  • 除了 AWS 开发工具包之外,没有任何代码接触到套接字,甚至不知道它们。所有 HTTP 工作都是通过 AWS SDK 专门完成的。
  • 因此,如果有什么东西关闭了它们,那一定是 AWS 开发工具包中的东西。
  • 代码在 EC2 服务器上运行;没有理由预计 EC2 和 S3 之间会出现任何类型的网络连接问题,当然也没有理由每次都应可预测地发生(运行一小时后)
4

4 回答 4

1

我不确定这是否是答案,但http://docs.aws.amazon.com/AmazonS3/latest/dev/request-rate-perf-considerations.html指出“如果您预计存储桶的请求速率为每秒超过 300 个 PUT/LIST/DELETE 请求或每秒超过 800 个 GET 请求,我们建议您打开支持案例以准备工作负载并避免对请求速率的任何临时限制”。也许因为我超过了限制,AWS 开始中止连接;SDK,检测空闲套接字,关闭它们,瞧!,我们得到异常。

更新:不确定这是否正确。亚马逊似乎声明,在这种情况下,您将收到明确的“减速”错误消息,而不是意外关闭。所以,谜题依然存在。

于 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 的请求仍处于挂起/未完成状态,导致线程等待()。一旦等待时间超过套接字超时,套接字就会关闭并抛出异常。

于 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

此异常只有一个原因。您或您的框架关闭了套接字,然后继续使用它。

于 2014-09-24T20:41:36.043 回答