[英]Http Client 4.5 not reusing the same connection using pooling connection manager in java
My below code is using pooling connection manager of apache http client 4.5 version.我下面的代码使用的是 apache http 客户端 4.5 版本的池连接管理器。 If I make a 50 requests, I am seeing in netstat 50 different tcp ports are being used, but at max using 5 connections alive any time.
如果我发出 50 个请求,我会在 netstat 中看到正在使用 50 个不同的 tcp 端口,但最多可以随时使用 5 个连接。 I have seen in wire shark also having filter
tcp.flags.syn==1 && tcp.flags.ack==0
it is creating 50 packets in filter, so it is using different connections rather than using the same connection, so why am not able to do?我在
tcp.flags.syn==1 && tcp.flags.ack==0
看到也有过滤器tcp.flags.syn==1 && tcp.flags.ack==0
它在过滤器中创建 50 个数据包,所以它使用不同的连接而不是使用相同的连接,所以为什么我不能吗?
my code:我的代码:
import javax.net.ssl.SSLContext;
import org.apache.http.HttpEntity;
import org.apache.http.HttpHost;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.routing.HttpRoute;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.util.EntityUtils;
import org.glassfish.jersey.SslConfigurator;
import org.json.JSONException;
import org.json.JSONObject;
public class App3Conn {
private static CloseableHttpClient client;
static String target="https://example.com";
static PoolingHttpClientConnectionManager cm ;
static{
SslConfigurator sslConfig = SslConfigurator.newInstance()
.securityProtocol("TLS")
.keyStoreFile("/Users/file")
.keyStorePassword("passw")
.keyStoreType("JKS")
.trustStoreFile("/Users/file");
SSLContext sslCtx = sslConfig.createSSLContext();
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslCtx,NoopHostnameVerifier.INSTANCE);
Registry<ConnectionSocketFactory> r = RegistryBuilder.<ConnectionSocketFactory>create()
.register("http", PlainConnectionSocketFactory.getSocketFactory())
.register("https", sslsf)
.build();
cm = new PoolingHttpClientConnectionManager(r);
cm.setMaxTotal(15);
cm.setDefaultMaxPerRoute(5);
client = HttpClients.custom().setSSLSocketFactory(sslsf).setConnectionManager(cm).build();
}
public static void main(String a[]) throws JSONException, ClientProtocolException, IOException
{
JSONObject jsonMessage = new JSONObject();
JSONObject jsonResponse;
jsonMessage.put("keyID", "keyID" );
StringEntity se = new StringEntity(jsonMessage.toString());
CloseableHttpResponse response2;
HttpPost httpPost = new HttpPost(target);
httpPost.setEntity(se);
httpPost.setHeader("Accept", "application/json");
httpPost.setHeader("Content-type", "application/json");
httpPost.setHeader("Connection", "keep-alive");
int i;
for(i=0;i<50;i++)
{
response2 = client.execute(httpPost);
HttpEntity entity2 = response2.getEntity();
String result = EntityUtils.toString(entity2);
EntityUtils.consume(entity2);
jsonResponse = new JSONObject(result);
String text = jsonResponse.getString("result");
response2.close();
}
}
}
I've seen this one before.我以前见过这个。 It was down to the way that the Apache connection pool works.
这取决于 Apache 连接池的工作方式。 An opaque
state
member is associated with the pool entry and must match to the requested state when a pool entry is requested (leased).不透明
state
成员与池条目相关联,并且在请求(租用)池条目时必须与请求的状态匹配。
When a connection lease attempt is made the state
requested is null
.当进行连接租用尝试时,请求的
state
为null
。 However when the connection is put back into the pool the state
is set to the X500Principal
object of the SSL peer.但是,当连接放回池中时,
state
将设置为 SSL 对等方的X500Principal
对象。 This happens in the DefaultUserTokenHandler
class.这发生在
DefaultUserTokenHandler
类中。 Luckily this is overridable when we create the HttpClient
class.幸运的是,当我们创建
HttpClient
类时,这是可以覆盖的。 Here's an example:下面是一个例子:
HttpClient apacheHttpClient = HttpClients.custom()
.setConnectionReuseStrategy(new DefaultConnectionReuseStrategy())
.setConnectionManager(new PoolingHttpClientConnectionManager(r))
.setUserTokenHandler(new UserTokenHandler() {
@Override
public Object getUserToken(HttpContext context) {
return null;
}
})
.build();
Do check that you're not losing anything that you depend on from DefaultUserTokenHandler
and don't use this method if the HttpClient
that you create can connect to multiple SSL peers through the same HTTP route.如果您创建的
HttpClient
可以通过相同的 HTTP 路由连接到多个 SSL 对等点,请检查您是否丢失了您依赖于DefaultUserTokenHandler
任何内容,并且不要使用此方法。 In my case this client is used to connect to a single SSL server.在我的情况下,此客户端用于连接到单个 SSL 服务器。
When you want to reuse the pool connection, don't close the response.当你想重用池连接时,不要关闭响应。 no need of response2.close();
不需要 response2.close(); response.close() closes all input/output resources and at last, closes tcp connection(socket).
response.close() 关闭所有输入/输出资源,最后关闭 tcp 连接(套接字)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.