上文查看是否复用连接的方法有误,当时方法是把route(ip与端口等)传给连接池,相同的请求第二次就能返回相同的对象。这是没错,但相同的对象并不代表复用了Socket(连接)。因为这个对象是org.apache.http.pool.RouteSpecificPool。为了搞明白它与连接的关系,是否复用了连接,还需深入分析下。先查看一下它的结构:
一、从Socket到CPoolEntry的过程
1.Socket被绑定到一个ManagedHttpClientConnection:
代码位于:org.apache.http.impl.conn.HttpClientConnectionOperator
2.而这个ManagedHttpClientConnection正是CPoolEntry的构造参数。
上图里的构造参数是LoggingManagedHttpClientConnection,它是ManagedHttpClientConnection的子类。也就是说结构是这样的:Socket->ManagedHttpClientConnection->CpoolEntry。
从上面知道查看是否复用了CPoolEntry,就可以说明是否复用了连接。因为CPoolEntry是Socket产生的。
还是发送两次相同请求,查看第二次是否复用了上一次连接,发现关键代码在这里,org.apache.http.impl.execchain.MainClientExec。在第二次请求时会判断这个连接是否关闭。
再进去看一下怎么判断这个连接是不可用的:
如图,从输入流读点数据。如果返回-1,没读到数据,就认为不可用,就要关闭了。这种情况一般是服务器关闭了。后面我测试不同httpClient发现,检测方法并不一样,4.3.3是这样的,4.5.3并不用这个方法。
三、编写测试是否复用方法
1.准备环境。
新建一个maven项目。引入httpclient 4.5.3。找到对象的源码包httpclient-4.5.3-sources.jar与httpcore-4.4.6-sources.jar,解压把源码放进本项目。再引入以下两个包
在org.apache.http.impl.conn.PoolingHttpClientConnectionManager增加以下一句打印日志:
使用同一个HttpClient对象,两次请求同一个HttpGet对象(url)。分两组,1组间隔20秒,1组间隔120秒。可以发现第二次返回的对象不一样,如下图:
有时候我们设置了超时、keepAlive等参数,但还是不知道到底服务器是否复用了连接,复用的有效期是多久。就可以通过这个方法来测试。