2015-05-29 17 views
6

Die Verwendung des AsyncHttpClient Providers mit Netty verhindert, dass das Hauptprogramm beendet wird, wenn wir eine asynchrone Anfrage ausführen. Zum Beispiel endet das folgende Programm nach den println oder nicht, je nachdem, ob der Anbieter JDKAsyncHttpProvider oder NettyAsyncHttpProvider:Wie wird AsyncHttpClient mit Netty für eine asynchrone HTTP-Anfrage geschlossen?

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

über die AsynHttpClient In der Dokumentation:

AHC ist eine Abstraktionsschicht das kann über das bloße JDK, Netty und Grizzly hinausgehen. Beachten Sie, dass die JDK-Implementierung sehr begrenzt ist und Sie die anderen realen Anbieter WIRKLICH nutzen sollten.

Um AsyncHttpClient mit Netty zu verwenden, müssen wir nur die entsprechende Bibliothek in den Java-Klassenpfad einfügen. So haben wir die vorherigen Program mit einer der folgenden Klassenpfad-Konfigurationen laufen kann Netty verwenden oder nicht:

  • -cp .;async-http-client-1.9.24.jar;netty-3.10.3.Final.jar;slf4j-api-1.7.12.jar verwenden NettyAsyncHttpProvider
  • -cp .;async-http-client-1.9.24.jar;slf4j-api-1.7.12.jarJDKAsyncHttpProvider

Was sonst noch verwenden sollten wir Möchten Sie Netty Provider richtig benutzen? Zum Beispiel schließe ich die AsyncHttpClient in AsyncCompletionHandler. Ist das korrekt?

Gibt es eine Konfiguration, um das beobachtete Verhalten zu ändern?

+0

Ist das nicht 'AsyncHttpClient' Thread-sicher? Erstellen Sie keine neue Methode für jeden Methodenaufruf. –

+0

Wenn Sie versuchen, den Client viel später zu schließen, z. nach 'thenAccept', würde Ihre Bewerbung enden? – ZhongYu

+0

Nein. Das Schließen des asyncHttpClient oder nicht, hat keinen Einfluss auf das resultierende Verhalten. –

Antwort

4

Mit dem netty-Provider und schrittweise durch den Debugger, sehe ich, dass Aufruf von asyncHttpClient.close() innerhalb der Rückruffunktion NioSocketChannelFactory.releaseExternalResources() fehlschlägt, wenn es versucht, das Herunterfahren zu tun. Es wird eine Ausnahme ausgelöst, die dazu führt, dass der Nicht-Dämonenthread verbleibt und das Beenden der VM verhindert wird. Die ausgelöste Ausnahme wird bei WARN protokolliert, sodass Sie sie wahrscheinlich nicht sehen (wenn Sie slf4j-log4j12-1.7.7.jar zu Ihrem Klassenpfad hinzufügen, sollten Sie sie sehen). Sie können also call() nicht im Callback aufrufen (und müssen es nach jeder Anfrage sowieso nicht mehr schließen).

Hier ist die Spur:

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)