我正在使用
中的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()调用。无论哪种方式,使用这种方法,问题不是我的。证明这是另一个故事。替代方案是某种其他解决方案,可以正确释放资源。
答案 0 :(得分:1)
如果您正在获取HTTP 500 Internal Server Error
,其 与您的客户端代码相关,或者您如何管理HTTP连接。问题完全在供应商方面。
答案 1 :(得分:0)
我会使用lsof查看哪些文件被打开。您还可以查看netstat -n -a以查看所有打开的连接。你有没有试过提高打开文件的限制,看看你是否可以解决这个问题?
答案 2 :(得分:0)
汤姆G在他的回答中是正确的,问题是在供应商方面,但我创建另一个答案的原因是虽然供应商没有关闭打开的文件句柄,但压力测试仍然崩溃。
我不得不切换到Jersey,这解决了&#34; httpclient.execute()&#34;在每个GET请求中执行打开/关闭操作,然后供应商必须给我一个修复问题的构建,因此有两个问题。
apache框架似乎存在问题,至少在我的实现方面存在问题,而Sun框架(Jersey)在我的压力测试中运行良好。
现在我需要使用真实代码进行测试。