【问题标题】:Java HttpGet, Too many open files in service errorJava HttpGet,服务中打开的文件过多错误
【发布时间】:2014-03-18 22:10:13
【问题描述】:

我正在使用来自

的 RESTFul HttpGet 服务

导入 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 连接然后关闭 他们为每个请求。更多时候不是你最终会挥之不去 连接。

我正在关闭“可关闭的”CloseableHttpClient,我也不认为我只需要一个。我应该补充一点,“我”没有用完任何东西,服务是。供应商似乎说该服务和操作系统一样完美。还可以做些什么来隔离问题?

更新 2: (我把服务端的日志文件发给了供应商,他们有以下说法。僵持?)

问题似乎是剩下的连接太多了 由您的界面打开。我包含了会话中的日志文件 火狐。您可以看到我如何通过 使用浏览器进行相同的连接。

初始连接只有一行

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

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

...您的日志文件显示:HTTP connection from [192.168.20.123]...ALLOWED

对于您发出的每个 GET 请求,这些连接都不会关闭。

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

CloseableHttpResponse response2 = httpclient.execute(oRestyGet);

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

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

【问题讨论】:

  • 您是否尝试过使用持久/流水线 HTTP 1.1 连接?
  • 我不确定那是什么或代码将如何改变。

标签: java rest httpclient


【解决方案1】:

如果您收到的是 HTTP 500 Internal Server Error,这与您的客户端代码或您如何管理 HTTP 连接无关。问题完全出在供应商方面。

【讨论】:

  • 我同意你的观点,但是会推迟接受这个答案,即问题出在供应商方面。我也应该能够创建/销毁 HTTP GET 请求对象,但是哦,好吧,还不如只拥有一个。上面的压力测试代码看起来很完整,应该可以工作。是否有替代解决方案是另一个话题。我将尝试捕获日志并发送给供应商。
  • 问题出现在服务/操作系统用完文件描述符 (FD) 之前。问题是一旦创建就释放连接,这不会发生。我检查了我可用的属性,并且 httpclient 的 close() 是唯一一个,我称之为。完全有可能httpclient有问题。很大程度上取决于我所调用的层的工程。
【解决方案2】:

我会使用 lsof 查看哪些文件处于打开状态。您还可以查看 netstat -n -a 以查看所有打开的连接。您是否尝试过提高打开文件限制以查看是否可以通过这种方式解决问题?

Too many open files ( ulimit already changed )

【讨论】:

  • 我不知道 lsof 命令。谢谢你。 lsof 命令显示了 1006 行相似的行。这些是我的压力测试请求。该服务在 1007 被炸毁,所以这是正确的。 “netstat -n -a”没有显示我看到的任何有趣的东西。整个命令的输出总数为 512,所以没关系。我假设 lsof 列出了 FD,这与供应商所说的相符。我该如何处理这些信息?
  • 我没有提高打开文件的限制,必须研究如何,但这不会有任何好处,因为问题会在稍后发生。一个请求等于一个打开的文件句柄,直到我关闭服务或重新启动操作系统。
【解决方案3】:

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

我不得不切换到Jersey,这解决了“httpclient.execute()”对每个 GET 请求执行打开/关闭操作的问题,然后供应商必须给我一个构建来解决他们的问题,因此有两个问题。

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-03
    • 2020-02-26
    • 1970-01-01
    • 2012-07-05
    相关资源
    最近更新 更多