To start the HTTPS server:
./gradlew run
To start the HTTP server (no TLS):
./gradlew run --args="--no-tls"
- JDK 11
Symptoms of CPU issue with HttpsServer
When connecting to the server with
curl -k https://localhost:8443/close
there is a response but one CPU gets used 100% until the server is shut down.
After starting the server (see above), send an HTTP request with curl:
curl -k https://localhost:8443/open
This will trigger the handler that leaves the stream to which we write the request body open. This works fine, it does not cause one CPU to be used 100%.
But this will:
curl -k https://localhost:8443/close
This other handler processing the request does close the stream. This will yield an HTTP response but the server becomes unresponsive afterwards due to high CPU load.
As helpfully suggested here, there's a workaround for this JDK bug:
applicationDefaultJvmArgs += [ "-Djdk.tls.acknowledgeCloseNotify=true" ]
- Arch Linux 5.1.7:
- OpenJDK 12.0.1+12
- OpenJDK 11.0.4+7
- OpenJDK 11.0.3+4
High CPU load does not occur when connecting to the HTTPS server using a browser (you'll have to accept the self-signed certificate first):
firefox https://localhost:8443/close
Also, using curl to connect to a regular HTTP server without TLS works fine:
./gradlew run --args="--no-tls"
curl http://localhost:8443/close
Findings from JDK Flight Recorder (JFR)
Directory with performance data gathered from JFR after calling curl -k https://localhost:8443/close
.
Instructions to get JFR.
The thread performing the most allocation is likely 'HTTP-Dispatcher'. This is the most common allocation path for that class:
SSLEngineImpl.writeRecord(ByteBuffer[], int, int, ByteBuffer[], int, int) (50.2 %)
SSLEngineImpl.wrap(ByteBuffer[], int, int, ByteBuffer[], int, int)
SSLEngineImpl.wrap(ByteBuffer[], int, int, ByteBuffer)
SSLEngine.wrap(ByteBuffer, ByteBuffer)
SSLStreams$EngineWrapper.wrapAndSendX(ByteBuffer, boolean)
SSLStreams.doClosure()
The most allocated class is likely 'javax.net.ssl.SSLEngineResult'. This is the most common allocation path for that class:
SSLEngineImpl.writeRecord(ByteBuffer[], int, int, ByteBuffer[], int, int) (100 %)
SSLEngineImpl.wrap(ByteBuffer[], int, int, ByteBuffer[], int, int)
SSLEngineImpl.wrap(ByteBuffer[], int, int, ByteBuffer)
SSLEngine.wrap(ByteBuffer, ByteBuffer)
SSLStreams$EngineWrapper.wrapAndSendX(ByteBuffer, boolean)
SSLStreams.doClosure()