问题
I've created a minimal application around Java's HttpsServer.
I've installed an HttpHandler that replies to a request with a short text message:
return exchange -> {
try {
OutputStream responseBodyStream = exchange.getResponseBody();
byte[] response = "Trouble with HTTPS and curl\n"
.getBytes(StandardCharsets.UTF_8);
exchange.getResponseHeaders().set("Content-Type", "text/plain");
exchange.sendResponseHeaders(200, response.length);
responseBodyStream.write(response);
responseBodyStream.close();
// Note that exchange.close() also closes the exchange's input stream
// and output stream
} catch (Exception e) {
log.warn("Could not handle request", e);
}
};
When connecting to the server with curl, the server responds but the Java process keeps using an entire core, thus rendering the server unresponsive.
It's this line that triggers the issue:
responseBodyStream.close();
If we remove the line, the server keeps on working.
From the docs:
In order to correctly terminate each exchange, the output stream must be closed, even if no response body is being sent.
I've created a project to reproduce the issue.
Some potential clues I've found up till now:
- High CPU usage only occurs when connecting to the server with curl. When connecting with Firefox, CPU usage stays low
- The issue does not occur with curl when using a regular HTTP server without TLS
- Data gathered using Flight Recorder indicate that
SSLEngineImpl#writeRecord
in the threadHTTP-Dispatcher
allocates a lot of objects
I'm on Arch Linux 5.1.7 using OpenJDK 12.0.1+12. The version of curl is 7.65.1.
Is this a bug in the JDK? Or am I using HttpsServer
the wrong way?
回答1:
I could also reproduce the problem.
There is an infinite loop in SSLStreams.doClosure
- this is definitely a JDK bug.
HttpsServer worked fine in JDK 10, but starts looping in JDK 11. I guess the problem is that HttpsServer implementation has not been adapted to TLS v1.3 half-close policy appeared in JDK 11.
Fortunately, there is a workaround. Add -Djdk.tls.acknowledgeCloseNotify=true
JVM option. With this option HttpsServer will work as expected. See JDK-8208526 for details.
来源:https://stackoverflow.com/questions/56708300/httpsserver-causes-100-cpu-load-with-curl