如何解决java.net.SocketException错误:打开文件太多

Eka*_*ogi 10 grails jmeter

我一直在使用JMeter对我的REST API进行负载测试.

当遇到1000个并发用户时,我收到以下错误:

Too many open files. Stacktrace follows:
java.net.SocketException: Too many open files
    at java.net.Socket.createImpl(Socket.java:397)
    at java.net.Socket.getImpl(Socket.java:460)
    at java.net.Socket.setSoTimeout(Socket.java:1017)
    at org.apache.http.conn.scheme.PlainSocketFactory.connectSocket(PlainSocketFactory.java:126)
    at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:180)
    at org.apache.http.impl.conn.ManagedClientConnectionImpl.open(ManagedClientConnectionImpl.java:294)
    at org.apache.http.impl.client.DefaultRequestDirector.tryConnect(DefaultRequestDirector.java:640)
    at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:479)
    at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:906)
    at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:805)
    at groovyx.net.http.HTTPBuilder.doRequest(HTTPBuilder.java:476)
    at groovyx.net.http.HTTPBuilder.doRequest(HTTPBuilder.java:441)
    at groovyx.net.http.HTTPBuilder.request(HTTPBuilder.java:390)
Run Code Online (Sandbox Code Playgroud)

我的服务器尝试命中另一个REST API以获取数据并对其进行处理,最后返回JSON响应.

如何增加Linux中打开文件的数量?

以下是我对另一台服务器的调用

Map getResponse(Map data, String url){
    HTTPBuilder httpBuilder = new HTTPBuilder(url);
    httpBuilder.request(Method.POST, JSON) {
        headers.'Authorization' = AppConfig.config.appKey;
        headers.'Content-type' = 'application/json'
        body = data
        response.success = { resp, reader ->
            return reader as Map;
        }
        response.failure = { response, reader ->
            return null
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

Rah*_*thi 5

您当然已经打开了最大数量的打开文件/套接字。默认情况下,Linux计算机上打开的文件或套接字的最大数量为1024。您需要更改它。您可以引用此java.net.SocketException打开文件过多

您可以使用以下查询从终端检查以获取允许的最大打开文件数

ulimit -n 
Run Code Online (Sandbox Code Playgroud)

这里

发生的事情是底层套接字没有关闭,最终JVM碰到了系统对打开文件描述符的每个进程的限制。

正确的解决方案是使套接字在正确的时间关闭(我猜是在服务器关闭其连接结束时或之后不久)。使用HttpURLConnection似乎很难。一切都很困惑:

  • connect()似乎只是立即将其关闭-否;Javadocs故意不清楚它的实际功能,特别是何时执行。

  • close()可能是正确的选择。Java错误#4147525的评估部分说:“ ...在输入和/或输出流上调用close()。这将正确地导致在不执行keepalive连接时关闭了基础套接字,并将正确地缓存和重用keepalive连接(无论如何,它们都会在短时间后超时并关闭自身)。”

  • 但也许不是。错误#4142971说:“调用close()方法对底层HTTP连接是否持久没有任何影响。”

如果没有明确的答案,则可以将HttpURLConnection对象添加到列表中,并在测试运行结束时立即将所有这些对象断开连接。那仍然会限制运行的总大小,但是至少丢失的描述符不会在运行之间累积。

也许真正的答案是放弃HttpURLConnection,而是使用Jakarta Commons的HTTP Client。有人建议将其与另一个问题联系起来(错误 #4143518)。

  • 这太棒了。无论我如何使用“HttpsUrlConnection”关闭和清理连接,我总是遇到“打开文件太多”的问题。我切换到“OkHttp”,它几乎开箱即用。我现在假设这是“HttpsUrlConnection”中的一个错误。 (2认同)