Hi, Have you considered upgrading to version 5? This would require code updates though.
Gary On Sun, Oct 11, 2020, 12:47 Arunan Sugunakumar <[email protected]> wrote: > Hi, > > We have used httpcore-NIO to implement a non-blocking server and with a > recent JAVA upgrade, we are finding a high CPU usage in our servers. While > we debugged, we found out that when we close the HTTPS connection on the > server-side, the WRITE event is getting fired continuously and the > connection close is unsuccessful. > > To explain the code, we have extended DefaultNHttpConnectionBase with our > own ServerConnection, and inside close() we simply just call the close() > method of the NHttpConnectionBase[1]. If we look at the code below, the > close method sets the status as CLOSING and after that either sets the > WRITE event in the session or tries to close the session (SSLIOSession in > our case). > > @Override > public void close() throws IOException { > if (this.status != ACTIVE) { > return; > } > this.status = CLOSING; > if (this.outbuf.hasData()) { > this.session.setEvent(EventMask.WRITE); > } else { > this.session.close(); > this.status = CLOSED; > } > } > > > Inside SSLIOSession close(), the updateEventMask() [2] is called. > > @Override > public synchronized void close() { > if (this.status >= CLOSING) { > return; > } > this.status = CLOSING; > if (this.session.getSocketTimeout() == 0) { > this.session.setSocketTimeout(1000); > } > try { > updateEventMask(); > } catch (final CancelledKeyException ex) { > shutdown(); > } > } > > > Inside updateEventMask() method, we get the HandshakeStatus from the JAVA > SSLEngine, and set a new Mask based on the status. > > switch (this.sslEngine.getHandshakeStatus()) { > case NEED_WRAP: > newMask = EventMask.READ_WRITE; > break; > case NEED_UNWRAP: > newMask = EventMask.READ; > break; > case NOT_HANDSHAKING: > newMask = this.appEventMask; > break; > case NEED_TASK: > break; > case FINISHED: > break; > } > > Before JDK upgrade, when outbound is closed, we used to get the status as > NEED_UNWRAP which sets the newMask as READ mask which closes the connection > in our server perfectly. > > But with a recent JDK commit[3], the new status is returned as > NOT_HANDSHAKING. > > Since mask is not set to READ because of the NOT_HANDSHAKING status, WRITE > event is continuously getting fired which makes the Server connection close > unsuccessful. > When the close is called multiple times for multiple connections, we could > observe that CPU usage increased continuosly and reached 100 percent and > stays there continuously. > > When I look at the stack trace, the execution flow was completely inside the > httpcore-nio component, which made our attempt to clear the Event from the > server implementation, unsuccessful. > > [image: Screenshot 2020-10-11 at 21.53.29.png] > > Earlier we were using Httpcore-NIO version 4.3.3. With this issue, we tried > upgrading to 4.4.13. But still the issue exists. The issue exists only for > HTTPS connection (where we use SSLIOSession) and not for HTTP connections. > > We observed the issue with the following JDK versions (which the contains the > commit[3]). > * Oracle JDK 1.8.0_261 (released in July 2020) > * AdoptOpenJDK (build 11.0.8+10) > * All versions after Oracle JDK 11.0.1 > > > It would be much helpful for us, if any help can be provided to resolve this > issue. > > [1] - > https://github.com/apache/httpcomponents-core/blob/rel/v4.4.13/httpcore-nio/src/main/java/org/apache/http/impl/nio/NHttpConnectionBase.java#L507 > [2] - > https://github.com/apache/httpcomponents-core/blob/rel/v4.4.13/httpcore-nio/src/main/java/org/apache/http/nio/reactor/ssl/SSLIOSession.java#L642 > [3] - > https://github.com/AdoptOpenJDK/openjdk-jdk11u/commit/8d1b63a4db2c6348a97b3cf45bd4d2caa7cad6b5#diff-e3c7d4bd31fed54c9607b6e0b6b2d43cL589 > > > Thanks in Advance. > > Regards, > Arunan > > -- > *Sugunakumar Arunan* > Software Engineer | WSO2 > > Email : [email protected] > Mobile : +94766016272 > Web : http://wso2.com > <https://wso2.com/signature> >
