有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

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

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

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

在我达到一定数量的流(通常大约2-300个并发流)之前,一切都运行得很好。在这之后的不规则点,几个(比如10个)线程将同时出现java.net.IOException: Connection reset错误

下载速度低于250mbit/s。大型实例。所有其他服务器方面的负载都很小(例如CPU、平均负载和内存使用都很好)

这可能是什么原因造成的,或者我怎样才能找到它


共 (5) 个答案

  1. # 1 楼答案

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

  2. # 2 楼答案

    他们可能会在VIP出现溢出问题,因为con-current连接的数量达到了极限。你可以缩小尺寸,看看

  3. # 3 楼答案

    你可能用完了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);,以防止临时端口在回收之前滞留

  4. # 4 楼答案

    猜测可能发生的事情并非无关紧要,但以下是一些提示,可能适用于您的上下文:

    • 你能检查一下你的shell(LinuxBash/zsh或任何其他)看看你是否提高了限制文件描述符(但也包括套接字)数量的标准限制吗, 带着bash shell的男人ulimit
    • 您是否在Java代码中明确关闭了流?不关闭溪流可能会引发这样聪明的问题
    • 试着在谷歌上搜索Linux TCP内核调优,看看你的ubuntu服务器是否有适合这种加载环境的堆栈

    嗯 杰罗姆

  5. # 5 楼答案

    出现此类问题的一个相对常见的原因是,中间代理(防火墙、负载平衡器)会丢弃它认为不活动(或寿命太长)的HTTP连接。 但除了这种普遍的可能性之外,EC2肯定还有其他人所说的更多问题