以前曾经说过为何我们不使用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