前面有提及到httpclient模拟系统之间的交互,如果系统之间的交互不高,是非常轻松的动作,不过httpclient是作为WEB容器的web请求存在,在http协议下,都是无状态的协议,也就是连接-请求-反馈-断开几个基本动作,好在现在WEB容器有了keep-alive的功能,包括很多负载均衡设备:如:LB、LVS、nginx、apache、jboss、tomcat等等都是支持的,虽然支持,但是看看上面的代码,就发现,每次请求都会重新建立连接,如何让他们不要重复创建连接呢?或者说在服务器端没有断开前不要重复创建连接,一个连接可以被使用多次请求,不至于一次请求就被断开一次;建立一次连接需要三次握手过程,以及更多的网络开销,所以你懂的。

道理很简单,其实和链接数据库差不多,将上面的请求的client对象以及method对象作为共享变量时,发起多次请求,平均效率会提升2倍左右,注意,这里是循环测试,而不是多线程。

但是对于并发较高的,我们不可能将method只用一个,因为它本身不能并发,于是我们就要用多个,在多个共享的对象中,如果控制好征用,有涉及到连接池的问题,不过这个连接池相对数据库的连接池要简单很多,因为,重试等动作,apache已经为你包装好了,你只需要顺序找和分配就可以了,如何降低竞争就是算法和策略的问题了。

但是,让客户端来编写这么一段代码是不是有点过分,当然你愿意写也是可以的,其实apache又为我们提供了一个后面就是异步httpclient(其实这里所知的异步并非真正的异步IO模式),也就是将这部分包装了,对于访问者来说还是同步的,只是在IO层面是非阻塞的了,这个就配合了服务器端的keep-alive,就像服务器端同时向一个站点请求多个资源时,我们希望是一个连接,而不是多个链接,其实在很多浏览器(如chrome、FF)都可以监控到它同时请求的服务器端资源,那么要用httpclient实现异步IO应该如何来做呢?其实也蛮简单的,下面是一个简单例子:

首先你要增加一个关于异步IO需要的包:

1、async-http-client包,可以在这里下载:https://oss.sonatype.org/content/repositories/releases/com/ning/async-http-client/1.6.2/

2、log4j的包,这个不用我说了,都知道在哪里

3、slf4j-spi 的包,目前用1.5以上的版本比较多。

4、slf4j-log4j 的包,可以看出,slf4j是在log4j基础上包装的。

OK,就这几个了,弄好后再看看下面这段代码,通过使用它,性能可以得到明显改善:

[java]  view plain
  1. AsyncHttpClient client = new AsyncHttpClient();  
  2. try {  
  3.    Future<Response> f = client.prepareGet("http://www.google.com.hk/").execute();  
  4.    System.out.println(f.get().getResponseBody("Big5"));//谷歌的输出编码集为Big5,反向解析结果的时候使用  
  5. }catch(...) {....}  


这段代码是不是超级简单,可以通过上面描述的三种方式:

1、直接调用

2、将GetMethod或PostMethod对象作为共享对象反复使用。

3、使用AsyncHttpClient

这三种方法,非别使用一次调用、循环多次调用、并发调用来测试性能,后面两者的性能比第一种方法的性能要高很多。

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐