处理文件描述符java

时间:2014-03-06 10:43:32

标签: java file-descriptor

每当我们的应用程序处理大量的http请求时,日志上都会显示“太多打开的文件”错误,我确信错误已连接到套接字并创建新的文件描述符实例,请参阅下面的错误:

[java.net.Socket.createImpl(Socket.java:447), java.net.Socket.getImpl(Socket.java:510), 
java.net.Socket.setSoTimeout(Socket.java:1101), 
org.apache.http.conn.scheme.PlainSocketFactory.connectSocket(PlainSocketFactory.java:122), 
org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnecti
onOperator.java:148), 
org.apache.http.impl.conn.AbstractPoolEntry.open(AbstractPoolEntry.java:149), 
org.apache.http.impl.conn.AbstractPooledConnAdapter.open(AbstractPooledConnAdapter.java:121), 
org.apache.http.impl.client.DefaultRequestDirector.tryConnect(DefaultRequestDirector.java:561), org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:415),

当我在互联网上看到我应该使用

EntityUtils.consume(entity);
httpClient.getConnectionManager().shutdown();

错误减少但不是很多,我感觉我的资源消耗不足以清除所有文件描述符。正确我正在寻找更改ulimit的不同答案,因为如果需要更改,应用程序将部署在我们无法配置的其他服务器上。

1 个答案:

答案 0 :(得分:0)

由于您使用的是Linux,因此可能会更改某些配置以解决问题。首先,发生了什么?在Java中关闭套接字后,操作系统将其设置为TIME_WAIT状态,这是因为仍然可能会将某些内容发送到套接字,因此操作系统会将其保持打开状态一段时间以确保收到所有数据包(基本上是仍然在路上的数据包,你需要接收某些响应)。

据我所知,这不是这个问题的最佳解决方案,但它确实有效。您应该将tcp_tw_recycletcp_tw_reuse设置为1,以允许操作系统快速重新使用套接字。现在它是如何完成的,取决于你拥有的Linux版本。例如在Fedora中我可以做类似的事情:

echo 1 > /proc/sys/net/ipv4/tcp_tw_reuse
echo 1 > /proc/sys/net/ipv4/tcp_tw_recycle

暂时设置(直到重启)。由你来了解如何永久地设置它们,因为我在Linux Administration上不是很强大。

编辑:我再次提到,它不是一个最佳解决方案,在尝试使用操作系统配置之前,先考虑应用程序中可以更改的内容。