How to close AsyncHttpClient with Netty for asynchronous Http request?

Using the AsyncHttpClient provider with Netty prevent the main program from terminating when executing an asynchronous request. For example, the following program exits after println or not, depending on whether the provider is JDKAsyncHttpProvider or NettyAsyncHttpProvider :

 public class Program { public static CompletableFuture<Response> getDataAsync(String uri) { final AsyncHttpClient asyncHttpClient = new AsyncHttpClient(); final CompletableFuture<Response> promise = new CompletableFuture<>(); asyncHttpClient .prepareGet(uri) .execute(new AsyncCompletionHandler<Response>(){ @Override public Response onCompleted(Response resp) throws Exception { promise.complete(resp); asyncHttpClient.close(); // ??? Is this correct ???? return resp; } }); return promise; } public static void main(String [] args) throws Exception { final String uri = "…"; System.out.println(getDataAsync(uri).get()); } } 

About AsynHttpClient , the documentation states:

AHC is an abstraction layer that can work on top of the bare JDK, Netty, and Grizzly. Please note that the JDK implementation is very limited, and you must REALLY use other real providers.

To use AsyncHttpClient with Netty, we just need to include the appropriate library in the java class path. Thus, we can run the previous Program with one of the following class path configurations to use Netty or not:

  • -cp .;async-http-client-1.9.24.jar;netty-3.10.3.Final.jar;slf4j-api-1.7.12.jar will use NettyAsyncHttpProvider
  • -cp .;async-http-client-1.9.24.jar;slf4j-api-1.7.12.jar will use JDKAsyncHttpProvider

What else needs to be done to use the Netty provider correctly? For example, I close AsyncHttpClient in AsyncCompletionHandler . It is right?

Is there any configuration to change the observed behavior?

+6
source share
1 answer

Using netty provider and stepping it in the debugger, I see that calling asyncHttpClient.close () inside the callback causes NioSocketChannelFactory.releaseExternalResources () to crash when trying to terminate it. An exception is thrown, and this probably causes the non-daemon thread to remain, and vm is saved from exiting. The corrected exception is written to WARN, so you probably cannot see it (if you add slf4j-log4j12-1.7.7.jar to you classpath, you should see it). Thus, you cannot call close () in the callback (and you do not need to close it after each query execution).

Here's the trace:

  WARN [New I/O worker #1] (NettyAsyncHttpProvider.java:79) - Unexpected error on close java.lang.IllegalStateException: Must not be called from a I/O-Thread to prevent deadlocks! at org.jboss.netty.channel.socket.nio.AbstractNioSelector.shutdown(AbstractNioSelector.java:415) at org.jboss.netty.channel.socket.nio.NioWorker.shutdown(NioWorker.java:36) at org.jboss.netty.channel.socket.nio.AbstractNioWorkerPool.shutdown(AbstractNioWorkerPool.java:142) at org.jboss.netty.channel.socket.nio.NioClientSocketChannelFactory.releaseExternalResources(NioClientSocketChannelFactory.java:225) at com.ning.http.client.providers.netty.channel.ChannelManager.close(ChannelManager.java:355) at com.ning.http.client.providers.netty.NettyAsyncHttpProvider.close(NettyAsyncHttpProvider.java:70) at com.ning.http.client.AsyncHttpClient.close(AsyncHttpClient.java:336) at com.cie.program.Program$1.onCompleted(Program.java:23) 
+4
source

Source: https://habr.com/ru/post/988188/


All Articles