2015-05-29 27 views
6

Korzystanie z dostawcy AsyncHttpClient z Netty uniemożliwi zakończenie programu głównego po wykonaniu żądania asynchronicznego. Na przykład, poniższy program kończy się po println, lub nie, w zależności od tego, czy dostawca jest JDKAsyncHttpProvider lub NettyAsyncHttpProvider:Jak zamknąć AsyncHttpClient z Netty dla asynchronicznego żądania Http?

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()); 
    } 
} 

O AsynHttpClient stany dokumentacja:

AHC jest warstwą abstrakcji który może pracować nad JDK, Netty i Grizzly. Zauważ, że implementacja JDK jest bardzo ograniczona i powinieneś NAPRAWDĘ użyć innych prawdziwych dostawców.

Aby użyć AsyncHttpClient z Netty, wystarczy dołączyć odpowiednią bibliotekę do ścieżki klasy java. Tak więc, możemy uruchomić poprzednią Program z jednej z następujących konfiguracji toru klasa używać Netty, czy nie:

  • -cp .;async-http-client-1.9.24.jar;netty-3.10.3.Final.jar;slf4j-api-1.7.12.jar użyje NettyAsyncHttpProvider
  • -cp .;async-http-client-1.9.24.jar;slf4j-api-1.7.12.jar użyje JDKAsyncHttpProvider

Co jeszcze powinniśmy zrobić, aby poprawnie używać dostawcy Netty? Na przykład zamykam AsyncHttpClient w AsyncCompletionHandler. Czy to jest poprawne?

Czy istnieje konfiguracja umożliwiająca zmianę obserwowanego zachowania?

+0

nie jest 'AsyncHttpClient' wątku bezpieczny? Nie twórz nowego dla każdego wywołania metody. –

+0

, jeśli spróbujesz zamknąć klienta znacznie później, np. po 'thenAccept', czy twoja aplikacja zostanie rozwiązana? – ZhongYu

+0

Nie. Zamknięcie, lub nie, asyncHttpClient nie ma wpływu na wynikowe zachowanie. –

Odpowiedz

4

Korzystanie dostawcy Netty i wzmocnienie przez nią w debugger, widzę, że dzwoni asyncHttpClient.close() wewnątrz zwrotnego powoduje NioSocketChannelFactory.releaseExternalResources() na niepowodzenie, gdy próbuje zrobić jej zamknięcie. Wypisywany jest wyjątek, który prawdopodobnie powoduje pozostawienie wątku innego niż demon i uniemożliwianie wychodzenia z niego. Zgłoszony wyjątek jest rejestrowany w WARN, więc prawdopodobnie go nie widzisz (jeśli dodasz slf4j-log4j12-1.7.7.jar do ciebie ścieżkę klasy, powinieneś to zobaczyć). Tak więc nie można wywołać metody close() w wywołaniu zwrotnym (i nie trzeba jej zamykać po każdym uruchomieniu żądania).

Oto ślad:

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)