Java UrlConnection在高负载下触发“连接重置”异常。为什么?

时间:2012-02-02 17:30:00

标签: java networking concurrency amazon-s3 ioexception

我正在使用Java在Linux(Ubuntu 10)64位服务器上从Amazon S3流式传输文件。

我为每个文件使用一个单独的线程,每个文件打开一个HttpURLConnection,它会同时下载和处理每个文件。

一切都运行得很漂亮,直到我达到一定数量的流(通常大约2-300个并发流)。在此之后的不规则点,几个(例如10个)线程将同时开始遇到java.net.IOException: Connection reset错误

我限制了下载速度,远低于m1.large实例的250mbit / s限制。所有其他服务器方面的负载也很小(例如CPU,平均负载和内存使用都很好)。

导致这种情况的原因,或者我如何追踪它?

5 个答案:

答案 0 :(得分:4)

猜测可能发生的事情并不容易,但这是一些提示,可能有些可能适用于您的背景:

  • 你能检查一下你的shell(linux bash / zsh或其他),看看你是否提高了限制文件描述符数量的标准限制(但也是套接字), 男子ulimit与bash shell
  • 您是否在Java代码中明确关闭了流?不关闭流可能会导致这样聪明的问题
  • 尝试google for Linux TCP内核调优,试着看看你的ubuntu服务器是否有适合这种负载上下文的堆栈......

HTH 杰罗姆

答案 1 :(得分:2)

他们可能在VIP上出现溢出问题,因为并发连接的数量达到了极限。你可以减小尺寸,看看......

答案 2 :(得分:0)

这里的问题主要在于您的语言。高负载触发错误条件,错误条件导致异常。不是相反。

答案 3 :(得分:0)

这样的问题的一个相对常见的原因是中间代理(防火墙,负载均衡器)丢弃了它认为不活动(或太长寿命)的HTTP连接。 但除了这种普遍的可能性之外,EC2肯定会像其他人所暗示的那样扭曲。

答案 4 :(得分:0)

您可能已用尽ephemeral ports。当许多短期连接被快速打开和关闭时,这会在负载下发生。标准Java HttpURLConnection不会为您提供设置正确套接字选项所需的灵活性。我建议使用Apache HttpComponents项目,并设置类似的选项......

...
HttpGet httpGet = new HttpGet(uri);
HttpParams params = new BasicHttpParams();
params.setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, 16 * 1000); // 16 seconds
params.setParameter(CoreConnectionPNames.SO_REUSEADDR, true); // <-- teh MOJO!

DefaultHttpClient httpClient = new DefaultHttpClient(connectionManager, params);
BasicHttpContext httpContext = new BasicHttpContext();
HttpResponse httpResponse = httpClient.execute(httpGet, httpContext);

StatusLine statusLine = httpResponse.getStatusLine();
if (statusLine.getStatusCode() >= HTTP_STATUS_CODE_300)
{
...

我省略了一些代码,比如connectionManager设置,但你可以从他们的文档中删除它。

[更新] 您还可以添加params.setParameter(CoreConnectionPNames.SO_LINGER, 1);以防止临时端口在回收之前徘徊。