My below code is using pooling connection manager of apache http client 4.5 version. 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. 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?
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. An opaque state member is associated with the pool entry and must match to the requested state when a pool entry is requested (leased).
When a connection lease attempt is made the state requested is null. However when the connection is put back into the pool the state is set to the X500Principal object of the SSL peer. This happens in the DefaultUserTokenHandler class. Luckily this is overridable when we create the HttpClient class. 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. In my case this client is used to connect to a single SSL server.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With