Как закрыть AsyncHttpClient с Netty для асинхронного Http-запроса?

С помощью AsyncHttpClient С Netty поставщик предотвратит завершение основной программы при выполнении асинхронного запроса. Например, следующая программа завершается после println, или нет, в зависимости от поставщика JDKAsyncHttpProvider или 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());
    }
}

о AsynHttpClient в документации:

AHC-это слой абстракции, который может работать поверх голого JDK, Netty и Grizzly. Обратите внимание, что реализация JDK очень ограничен,и вы действительно должны использовать других реальных поставщиков.

чтобы использовать AsyncHttpClient с Netty, нам просто нужно включить соответствующую библиотеку в путь к классу java. Итак, мы можем запустить предыдущий Program С одной из следующих конфигураций пути класса для использования Netty или нет:

  • -cp .;async-http-client-1.9.24.jar;netty-3.10.3.Final.jar;slf4j-api-1.7.12.jar использовать NettyAsyncHttpProvider
  • -cp .;async-http-client-1.9.24.jar;slf4j-api-1.7.12.jar использовать JDKAsyncHttpProvider

что еще мы должны сделать, чтобы использовать поставщика Нетти правильно? Например, я закрываю AsyncHttpClient на AsyncCompletionHandler. Это верно?

есть ли настройки для изменения наблюдаемого поведения?

1 ответов


используя поставщик netty и проходя через него в отладчике, я вижу, что вызов asyncHttpClient.close () внутри обратного вызова вызывает NioSocketChannelFactory.releaseExternalResources () для сбоя при попытке выполнить его завершение работы. Создается исключение, и это, скорее всего, приведет к тому, что поток не демона останется и не позволит виртуальной машине выйти. Исключение регистрируется при предупреждении, поэтому вы, вероятно, не видите его (если вы добавляете slf4j-log4j12-1.7.7.jar для вас classpath вы должны увидеть он.) Таким образом, вы не можете вызвать close() в обратном вызове (и вам не нужно закрывать его после каждого выполнения запроса).

вот трассировка:

 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.onCompleted(Program.java:23)