Java HttpGet,服务错误中打开的文件过多

时间:2014-03-18 22:10:13

标签: java rest httpclient

我正在使用

中的RESTFul HttpGet服务

import org.apache.http.client.methods.HttpGet;

我创建了一个函数来查询另一台计算机上的服务。该调用工作正常,但我在服务上遇到“太多打开的文件”。我的方只是返回一个500错误,我抓住了。

我与供应商进行了交谈,他们非常坚定地认为RESTful调用应该以持久的方式进行,并且我根本不会释放某些东西,并继续说问题就在我身边。

我写了一个压力函数,见下文,以帮助隔离问题。据我所知,我正在释放一切。我还是Java的新手,所以我只是没有看到一些不清楚的东西。

import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;

public void doStressTest()
{
    String strUri = "http://<ip address>:<port>/task?vara=dataa&varb=datab";
    HttpGet oRestyGet = new HttpGet();
    oRestyGet.addHeader("Accept", "application/xml");

    for (int iLoop = 0; iLoop < 1000; iLoop++)
    {
        CloseableHttpClient httpclient = HttpClients.createDefault();
        try
        {
            oRestyGet.setURI(new URI(strUri));
            try
            {
                CloseableHttpResponse response2 = httpclient.execute(oRestyGet);
                try
                {
                    String strResponseHeader = response2.getStatusLine().toString();
                    if (false == "HTTP/1.1 200 OK".equalsIgnoreCase(strResponseHeader))
                        return;

                    continue;
                }
                finally
                {
                    response2.close();
                }
            }
            catch (ClientProtocolException e)
            {
                e.printStackTrace();
            }
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
        finally
        {
            try
            {
                httpclient.close();
            }
            catch (Exception e)
            {
                e.printStackTrace();
            }
        }
    }

    try
    {
        oRestyGet.releaseConnection();
    }
    catch (Exception e)
    {
        e.printStackTrace();
    }
}

更新: 我认为我添加了供应商所说的内容,以防它可能有所帮助。我应该在下面的压力测试中添加一个,我打开一个HTTP GET请求对象,对于我的“会话”是持久的并用于整个请求。

  

这意味着系统正在耗尽正在运行的用户的FD   这个过程。当有太多打开的套接字或FD时会发生这种情况。   通常使用HTTP,强烈建议使用HTTP请求   以持久的方式发送,即你有一个HTTP连接   整个会话,而不是打开多个HTTP连接然后关闭   他们为每个请求。更常见的是,你最终没有挥之不去   连接。

我正在关闭“closeable”CloseableHttpClient,我也不认为我只需要一个。我应该补充一点,“我”没有任何东西,服务是。供应商似乎表示该服务与操作系统一样完美。还有什么办法可以解决这个问题?

更新2: (我将服务中的日志文件发送给供应商,他们有以下说法。僵局?)

  

看起来问题是剩下的连接太多了   通过您的界面打开。我在会话中包含了日志文件   Firefox浏览器。你可以看到我如何通过它发出多个HTTP请求   使用浏览器的相同连接。

     

初始连接只有一行

     

来自[127.0.0.1]的HTTP连接...允许

     

后续的GET请求来自同一个连接。

     

...您的日志文件显示:来自[192.168.20.123] ...允许的HTTP连接

     

您发出的每个GET请求,并且这些连接未关闭。

更新3: 我可以访问服务生成的日志,但无法访问源。 Java将连接和GET请求作为一个包发出,以响应该行:

CloseableHttpResponse response2 = httpclient.execute(oRestyGet);

我发出了httpclient.close(),它没有生成日志条目,所以我怀疑该服务根本没有响应。

由于我不熟悉另一端的机制,也许服务只是响应事件,而问题是CENTOS没有正确处理close()调用。无论哪种方式,使用这种方法,问题不是我的。证明这是另一个故事。替代方案是某种其他解决方案,可以正确释放资源。

3 个答案:

答案 0 :(得分:1)

如果您正在获取HTTP 500 Internal Server Error,其 与您的客户端代码相关,或者您如何管理HTTP连接。问题完全在供应商方面。

答案 1 :(得分:0)

我会使用lsof查看哪些文件被打开。您还可以查看netstat -n -a以查看所有打开的连接。你有没有试过提高打开文件的限制,看看你是否可以解决这个问题?

Too many open files ( ulimit already changed )

答案 2 :(得分:0)

汤姆G在他的回答中是正确的,问题是在供应商方面,但我创建另一个答案的原因是虽然供应商没有关闭打开的文件句柄,但压力测试仍然崩溃。

我不得不切换到Jersey,这解决了&#34; httpclient.execute()&#34;在每个GET请求中执行打开/关闭操作,然后供应商必须给我一个修复问题的构建,因此有两个问题。

apache框架似乎存在问题,至少在我的实现方面存在问题,而Sun框架(Jersey)在我的压力测试中运行良好。

现在我需要使用真实代码进行测试。