HttpsServer导致curl造成100%的CPU负载

时间:2019-06-21 17:52:18

标签: java performance curl https server

我已经围绕Java的HttpsServer创建了一个最小的应用程序。

我已经安装了HttpHandler,该请求通过短信回复了请求:

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

  

为了正确终止每个交换,即使没有发送响应主体,也必须关闭输出流。

我已经创建了a project to reproduce个问题。

到目前为止,我已经发现了一些潜在线索:

  • 仅当使用curl连接到服务器时,CPU使用率较高。与Firefox连接时,CPU使用率仍然较低
  • 使用不带TLS的常规HTTP服务器时,curl不会出现此问题
  • 使用Flight Recorder收集的数据表明线程SSLEngineImpl#writeRecord中的HTTP-Dispatcher分配了很多对象

我在使用OpenJDK 12.0.1 + 12的Arch Linux 5.1.7上。 curl的版本是7.65.1。

这是JDK中的错误吗?还是我以错误的方式使用HttpsServer

1 个答案:

答案 0 :(得分:3)

我也可以重现问题。
SSLStreams.doClosure中存在一个无限循环-这绝对是一个JDK错误。

HttpsServer在JDK 10中工作正常,但在JDK 11中开始循环。我想问题是HttpsServer实现尚未适应JDK 11中出现的TLS v1.3半关闭策略。

幸运的是,有一种解决方法。添加-Djdk.tls.acknowledgeCloseNotify=true JVM选项。使用此选项,HttpsServer将按预期工作。有关详细信息,请参见JDK-8208526