IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

    再谈AsyncHttpClient

    hongjiang发表于 2016-07-04 08:08:23
    love 0

    以前曾经说过为何我们不使用AsyncHttpClient,当时主要是从需求出发,性能上不需要。不过在业务做活动推广的场景下,性能上是必须要考虑的;另外在Actor模型里,要调用第三方的http接口,为了避免Actor收发消息的底层线程池被阻塞也必须用异步的方式。在去年年底我们的一次活动,Akka里使用AsyncHttpClient(1.9版本)已经很好的验证过它们的组合以及惊诧的性能了。

    最近看到AsyncHttpClient在2.0后被重构了,包名从com.ning变为了org.asynchttpclient,里面的一些类也有所重构,也升级了所依赖的netty的版本。最近正好一些新项目里调用第三方的http接口,尝试了一下新的AsyncHttpClient,结果发现它的readTimeout参数并不work,下面是两个版本的测试程序:

    import com.ning.http.client.AsyncCompletionHandler;
    import com.ning.http.client.AsyncHttpClientConfig;
    import com.ning.http.client.Response;
    
    public class AsyncV1Test {
    
        static class MyCallback extends AsyncCompletionHandler<Boolean> {
    
            @Override
            public Boolean onCompleted(Response response) throws Exception {
                System.out.println(response.getResponseBody());
                return true;
            }
    
            public void onThrowable(Throwable t) {
                t.printStackTrace(System.err);
            }
        }
    
        public static void main(String[] args) throws Exception {
            AsyncHttpClientConfig cfg = new AsyncHttpClientConfig.Builder().setReadTimeout(100).build();
            com.ning.http.client.AsyncHttpClient cli = new com.ning.http.client.AsyncHttpClient(cfg);
            cli.prepareGet("http://localhost:8080/sleep?time=200").execute(new MyCallback());
    
            // wait and quit
            Thread.sleep(1000);
            cli.close();
        }
    }
    

    上面是老版本的com.ning的客户端的readTimeout测试,设置的是100毫秒,请求的url在server端会sleep 200毫秒,超时的异常符合预期:

    java.util.concurrent.TimeoutException: Read timeout to localhost/127.0.0.1:8080 of 100 ms
        at com.ning.http.client.providers.netty.request.timeout.TimeoutTimerTask.expire(TimeoutTimerTask.java:47)
        at com.ning.http.client.providers.netty.request.timeout.ReadTimeoutTimerTask.run(ReadTimeoutTimerTask.java:57)
        at org.jboss.netty.util.HashedWheelTimer$HashedWheelTimeout.expire(HashedWheelTimer.java:556)
        at org.jboss.netty.util.HashedWheelTimer$HashedWheelBucket.expireTimeouts(HashedWheelTimer.java:632)
        at org.jboss.netty.util.HashedWheelTimer$Worker.run(HashedWheelTimer.java:369)
        at org.jboss.netty.util.ThreadRenamingRunnable.run(ThreadRenamingRunnable.java:108)
        at java.lang.Thread.run(Thread.java:745)
    

    在新版本的org.asynchttpclient里测试同样的逻辑:

    import org.asynchttpclient.AsyncCompletionHandler;
    import org.asynchttpclient.DefaultAsyncHttpClient;
    import org.asynchttpclient.DefaultAsyncHttpClientConfig;
    import org.asynchttpclient.Response;
    
    public class AsyncV2Test {
    
        static class MyCallback extends AsyncCompletionHandler<Boolean> {
    
            @Override
            public Boolean onCompleted(Response response) throws Exception {
                System.out.println(response.getResponseBody());
                return true;
            }
    
            public void onThrowable(Throwable t) {
                t.printStackTrace(System.err);
            }
        }
    
        public static void main(String[] args) throws Exception{
    
            DefaultAsyncHttpClientConfig cfg = new DefaultAsyncHttpClientConfig.Builder().setReadTimeout(100).build();
            org.asynchttpclient.AsyncHttpClient cli = new DefaultAsyncHttpClient(cfg);
            cli.prepareGet("http://localhost:8080/sleep?time=200").execute(new MyCallback());
    
            // wait and quit
            Thread.sleep(1000);
            cli.close();
        }
    }       
    

    却没有发生超时的异常,而是正常打印出了最终的请求结果。估计是新版本重构后所带来的bug,我还是回退到老的com.ning.http.client.AsyncHttpClient



沪ICP备19023445号-2号
友情链接