6

当我们执行异步请求时,使用AsyncHttpClientwithNetty提供程序将阻止主程序终止。例如,以下程序在 , 之后终止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

我们还应该做什么才能正确使用 Netty 提供者?例如,我正在关闭AsyncHttpClientin AsyncCompletionHandler。那是对的吗?

是否有任何配置可以改变观察到的行为?

4

1 回答 1

5

使用 netty 提供程序并在调试器中单步执行它,我看到在回调中调用 asyncHttpClient.close() 会导致 NioSocketChannelFactory.releaseExternalResources() 在尝试关闭时失败。抛出异常,这可能会导致非守护线程保留,并阻止 vm 退出。抛出的异常记录在 WARN 中,因此您可能看不到它(如果将 slf4j-log4j12-1.7.7.jar 添加到类路径中,您应该会看到它)。所以你不能在回调中调用 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$1.onCompleted(Program.java:23)
于 2015-06-04T21:27:50.117 回答