Connection pooling 使用apache.DefaultHttpClient的Http连接进入时间\u等待未被重用

Connection pooling 使用apache.DefaultHttpClient的Http连接进入时间\u等待未被重用,connection-pooling,apache-httpclient-4.x,keep-alive,httpconnection,time-wait,Connection Pooling,Apache Httpclient 4.x,Keep Alive,Httpconnection,Time Wait,我们有一个HttpClient(apache.DefaultHttpClient)对象池(GenericObjectPool)。HttpPost对象通过这些客户端被放入以执行,这些客户端可能会同时发送Post请求。使用的协议是:带有keepalive的HTTP/1.1 在通过netstat进行负载测试期间,可以观察到新的套接字连接被不加区分地创建,而旧的连接被转到TIME\u WAIT 日志摘录:- [Worker-2] org.apache.http.impl.conn.Wire 63 -

我们有一个HttpClient(apache.DefaultHttpClient)对象池(GenericObjectPool)。HttpPost对象通过这些客户端被放入以执行,这些客户端可能会同时发送Post请求。使用的协议是:带有keepalive的HTTP/1.1

在通过netstat进行负载测试期间,可以观察到新的套接字连接被不加区分地创建,而旧的连接被转到TIME\u WAIT


日志摘录:-

[Worker-2] org.apache.http.impl.conn.Wire 63 - >> "POST /INBOX/4504a09e-13c0-3853-a285-9e2b9a22f65e/1e1e5a20-a8c1-11e2-99b8-7c19e9129271 HTTP/1.1[\r][\n]"

[Worker-2] org.apache.http.impl.conn.Wire 63 - >> "Content-Type: application/json; charset=UTF-8[\r][\n]"

[Worker-2] org.apache.http.impl.conn.Wire 63 - >> "Content-Length: 117[\r][\n]"

[Worker-2] org.apache.http.impl.conn.Wire 63 - >> "Host: rwcdtgxb0402:15010[\r][\n]"

[Worker-2] org.apache.http.impl.conn.Wire 63 - >> "Connection: Keep-Alive[\r][\n]"

[Worker-2] org.apache.http.impl.conn.Wire 63 - >> "User-Agent: Apache-HttpClient/4.2.1 (java 1.5)[\r][\n]"

[Worker-2] org.apache.http.impl.conn.Wire 63 - >> "[\r][\n]"

[Worker-2] org.apache.http.impl.conn.Wire 63 - << "HTTP/1.1 200 OK[\r][\n]"

[Worker-2] org.apache.http.impl.conn.Wire 63 - << "Content-Length: 0[\r][\n]"

[Worker-2] org.apache.http.impl.conn.Wire 63 - << "[\r][\n]"

[Worker-2] org.apache.http.impl.conn.DefaultClientConnection 254 - Receiving response: HTTP/1.1 200 OK

[Worker-2] org.apache.http.impl.conn.DefaultClientConnection 257 - << HTTP/1.1 200 OK

[Worker-2] org.apache.http.impl.conn.DefaultClientConnection 260 - << Content-Length: 0

[Worker-2] org.apache.http.impl.client.DefaultRequestDirector 540 - Connection can be kept alive indefinitely

**[Worker-2] org.apache.http.impl.conn.DefaultClientConnection 154 - Connection 0.0.0.0:51211<->192.168.88.172:15010 shut down**

[Worker-2] org.apache.http.impl.conn.BasicClientConnectionManager 189 - Releasing connection org.apache.http.impl.conn.ManagedClientConnectionImpl@12f65ce5
[Worker-2]org.apache.http.impl.conn.Wire 63->“POST/INBOX/4504a09e-13c0-3853-a285-9e2b9a22f65e/1e1e5a20-a8c1-11e2-99b8-7c19e9129271 http/1.1[\r][\n]”
[Worker-2]org.apache.http.impl.conn.Wire 63->>“内容类型:application/json;charset=UTF-8[\r][\n]”
[Worker-2]org.apache.http.impl.conn.Wire 63->>“内容长度:117[\r][\n]”
[Worker-2]org.apache.http.impl.conn.Wire 63->>“主机:rwcdtgxb0402:15010[\r][\n]”
[Worker-2]org.apache.http.impl.conn.Wire 63->>“连接:保持活动[\r][\n]”
[Worker-2]org.apache.http.impl.conn.Wire 63->>“用户代理:apache HttpClient/4.2.1(java 1.5)[\r][\n]”
[Worker-2]org.apache.http.impl.conn.Wire 63->>“[\r][\n]”

[Worker-2]org.apache.http.impl.conn.Wire 63-几天前解决了问题

错误:在HttpClient对象上调用releaseConnection()。但是,避免它也不能解决问题

更正: 为保持连接处于活动状态(处于已建立状态)而采取的措施是通过以下示例代码:

HttpClient client = new org.apache.http.impl.client.DefaultHttpClient();
...
org.apache.http.HttpResponse response = client.executed(HttpPost) ;
org.apache.http.HttpEntity en = response.getEntity();
if (en != null) {
  en.getContent().close();
}
一旦收到HttpResponse,为了重用和维护创建的连接,只需关闭http响应上的InputStream(en.getContent())。不要在HttpPost或客户端对象上调用任何其他发布方法


用JMeter负载测试了这个处理,发现它可以工作。还没有观察到任何副作用

注意调用
EntityUtils.console(entity)
做得更多,应该使用:

    /**
     * Ensures that the entity content is fully consumed and 
     * the content stream, if exists, is closed.
     *
     * @param entity the entity to consume.
     * @throws IOException if an error occurs reading the input stream
     *
     * @since 4.1
     */
    public static void consume(final HttpEntity entity) throws IOException {
        if (entity == null) {
            return;
        }
        if (entity.isStreaming()) {
            final InputStream inStream = entity.getContent();
            if (inStream != null) {
                inStream.close();
            }
        }
    }
EntityUtils.consume(实体)也会这样做。
EntityUtils.consume(实体)
处理得更好,应该使用它,请参见我的答案