3

We are getting the below error frequently in our production. The reason is, server closes the connection and the client is trying with half closed stale connection. we have eviction strategy which runs every 80 minutes periodically which will check for expired and idle connections and close them. still we are getting this errors. we are planning to reduce the eviction thread interval to 40 minutes. is there any other solution available to stop this errors?

We are using PoolingNHttpClientConnectionManager. idle period timeout is 60 seconds.httpasyncclient version is 4.1.1.

org.apache.http.ConnectionClosedException: Connection closed
        at org.apache.http.nio.protocol.HttpAsyncRequestExecutor.endOfInput(HttpAsyncRequestExecutor.java:341)
        at org.apache.http.impl.nio.DefaultNHttpClientConnection.consumeInput(DefaultNHttpClientConnection.java:263)
        at org.apache.http.impl.nio.client.InternalIODispatch.onInputReady(InternalIODispatch.java:81)
        at org.apache.http.impl.nio.client.InternalIODispatch.onInputReady(InternalIODispatch.java:39)
        at org.apache.http.impl.nio.reactor.AbstractIODispatch.inputReady(AbstractIODispatch.java:123)
        at org.apache.http.impl.nio.reactor.BaseIOReactor.readable(BaseIOReactor.java:164)
        at org.apache.http.impl.nio.reactor.AbstractIOReactor.processEvent(AbstractIOReactor.java:339)
        at org.apache.http.impl.nio.reactor.AbstractIOReactor.processEvents(AbstractIOReactor.java:317)
        at org.apache.http.impl.nio.reactor.AbstractIOReactor.execute(AbstractIOReactor.java:278)
        at org.apache.http.impl.nio.reactor.BaseIOReactor.execute(BaseIOReactor.java:106)
        at org.apache.http.impl.nio.reactor.AbstractMultiworkerIOReactor$Worker.run(AbstractMultiworkerIOReactor.java:590)
        at java.lang.Thread.run(Thread.java:748)
Vadim Kotov
  • 8,084
  • 8
  • 48
  • 62

1 Answers1

1

There are two options:

  1. Define a finite TTL (total time to live) limit for all connections at the connection manager construction time
  2. Use a custom ConnectionKeepAliveStrategy implementation to enforce a relative expiration time for persistent connections.

Here is example of HttpAsyncClient configuration that enforces a total time to live limit of 2 minute and relative expiration time of 30 seconds

Please note this may not completely eliminate the issue as both endpoints, the client and the server, may close connections at any point of time without a prior handshake.

ConnectingIOReactor ioReactor = new DefaultConnectingIOReactor(IOReactorConfig.custom()
        .build());
PoolingNHttpClientConnectionManager cm = new PoolingNHttpClientConnectionManager(
        ioReactor,
        ManagedNHttpClientConnectionFactory.INSTANCE,
        RegistryBuilder.<SchemeIOSessionStrategy>create()
                .register("http", NoopIOSessionStrategy.INSTANCE)
                .register("https", SSLIOSessionStrategy.getSystemDefaultStrategy())
                .build(),
        DefaultSchemePortResolver.INSTANCE,
        SystemDefaultDnsResolver.INSTANCE,
        2,
        TimeUnit.MINUTES);
CloseableHttpAsyncClient client = HttpAsyncClients.custom()
        .setConnectionManager(cm)
        .setConnectionManagerShared(false)
        .setKeepAliveStrategy(new DefaultConnectionKeepAliveStrategy() {
            @Override
            public long getKeepAliveDuration(HttpResponse response, HttpContext context) {
                long keepAliveDuration = super.getKeepAliveDuration(response, context);
                if (keepAliveDuration > 30000) {
                    keepAliveDuration = 30000;
                }
                return keepAliveDuration;
            }
        })
        .build();
ok2c
  • 26,450
  • 5
  • 63
  • 71
  • Thanks for your response. But important thing is, even if we set TTL or keep alive time, again clientside connection will be lost when a transaction is on the fly. the same error we will get at client end. is there a configuration which restricts the number of hits(like, number of requests which a connection can serve)? Otherwise, unfortunately, retrying will be the only solution I guess :(. . – Sudha Rajamanickam Dec 08 '19 at 15:36
  • I am not sure I understand what it is exactly you are asking, but as I have already said both endpoints can close the connection on their end at any point of time, so request re-execution is the only solution that works in call cases. The options I have offered you radically reduce the possibility of request failures to due the opposite endpoint closing persistent connections. – ok2c Dec 08 '19 at 22:13
  • why doesn't client resume the connection when it's closed but instead throws such an exception? – choxsword Feb 15 '22 at 09:27