【问题标题】:HttpsServer causes 100% CPU load with curlHttpsServer 使用 curl 导致 100% CPU 负载
【发布时间】:2019-11-04 14:12:18
【问题描述】:

我已经围绕 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 收集的数据表明线程HTTP-Dispatcher 中的SSLEngineImpl#writeRecord 分配了很多对象

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

这是 JDK 中的错误吗?还是我用错了HttpsServer

【问题讨论】:

    标签: java performance curl https server


    【解决方案1】:

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

    HttpsServer 在 JDK 10 中运行良好,但在 JDK 11 中开始循环。我猜问题是 HttpsServer 实现尚未适应 JDK 11 中出现的 TLS v1.3 半关闭策略。

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-04-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-01-14
      • 2014-08-29
      • 1970-01-01
      相关资源
      最近更新 更多