我已经围绕 Java 创建了一个最小的应用程序HttpsServer https://docs.oracle.com/en/java/javase/11/docs/api/jdk.httpserver/com/sun/net/httpserver/HttpsServer.html.
我已经安装了一个HttpHandler https://docs.oracle.com/en/java/javase/11/docs/api/jdk.httpserver/com/sun/net/httpserver/HttpHandler.html通过短信回复请求:
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);
}
};
当使用curl连接到服务器时,服务器响应,但Java进程继续使用整个核心,从而导致服务器无响应。
正是这一行触发了这个问题:
responseBodyStream.close();
如果我们删除该线路,服务器将继续工作。
来自docs https://docs.oracle.com/en/java/javase/11/docs/api/jdk.httpserver/com/sun/net/httpserver/HttpExchange.html#getResponseBody():
为了正确终止每次交换,即使没有发送响应主体,也必须关闭输出流。
我已经创建了一个可以重现的项目 https://github.com/mb720/https-server-cpu-bug问题。
到目前为止我发现的一些潜在线索:
- 仅当使用curl 连接到服务器时才会出现CPU 使用率过高的情况。使用 Firefox 连接时,CPU 使用率保持较低水平
- 使用不带 TLS 的常规 HTTP 服务器时,curl 不会出现此问题
- 收集的数据使用飞行记录仪 https://en.wikipedia.org/wiki/JDK_Flight_Recorder表明
SSLEngineImpl#writeRecord
在线程中HTTP-Dispatcher
分配很多对象
我使用的是 Arch Linux 5.1.7,使用 OpenJDK 12.0.1+12。卷曲的版本是7.65.1。
这是 JDK 中的错误吗?或者我正在使用HttpsServer
错误的方法?