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

How to resolve the error java.net.SocketException: Too many open files

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

我遇到 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)

我的服务器尝试访问另一个 REST API 来获取数据并进行处理,最后 return 一个 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
        }
    }
}

你肯定已经打开了最大打开数file/sockets。 Linux 机器上打开的文件或套接字的最大数量默认为 1024。你需要改变它。你可以参考这个 java.net.SocketException Too many open files

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

ulimit -n 

来自here

What's happening is that the underlying sockets aren't being closed, and eventually the JVM bumps into the system's per-process limit on open file descriptors.

The right solution would be to make the sockets close at the Right Time (which I guess is when, or shortly after, the server has closed its end of the connection). That seems hard with HttpURLConnection. It's all very confused:

  • disconnect() just seems to close it immediately -- or not; the Javadocs are intentionally vague about what it actually does, and especially when it does it.

  • close() might be the right choice. The Evaluation section of Java bug #4147525 says: "... call close() on the input and/or output stream. This will correctly result in the underlying socket being closed when you aren't doing keepalive connections and will correctly cache and reuse keepalive connections (and which will timeout and close themselves after a short time anyway)."

  • But maybe not. Bug #4142971 says: "Calling the close() methods has no effect one way or the other on whether the underlying HTTP connection is persistent."

Failing a clear answer, perhaps the HttpURLConnection objects could be added to a list, and all disconnected at once at the end of the test run. That'd still limit the total size of the run, but at least the lost descriptors wouldn't accumulate between runs.

Maybe the real answer is to give up on HttpURLConnection, and instead use the HTTP Client from Jakarta Commons. Someone suggested that in connection with a different problem (bug #4143518).

"java.net.SocketException: Too many files open"可以看到任何 Java 服务器应用程序,例如Tomcat、Weblogic、WebSphere 等,客户端连接和断开连接频繁。

You can find out how to solve "java.net.SocketException: Too many files open" here