我下面的代码使用的是 apache http 客户端 4.5 版本的池连接管理器。如果我发出 50 个请求,我会在 netstat 中看到正在使用 50 个不同的 tcp 端口,但最多可随时使用 5 个连接。我在wireshark中看到也有过滤tcp.flags.syn==1 && tcp.flags.ack==0器,它在过滤器中创建50个数据包,所以它使用不同的连接而不是使用相同的连接,那么为什么不能呢?
我的代码:
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();
}
}
}
Run Code Online (Sandbox Code Playgroud)
我以前见过这个。这取决于 Apache 连接池的工作方式。不透明state成员与池条目相关联,并且在请求(租用)池条目时必须与请求的状态匹配。
当进行连接租用尝试时,state请求的是null。但是,当连接放回池中时,该连接将state设置为X500PrincipalSSL 对等方的对象。这发生在DefaultUserTokenHandler课堂上。幸运的是,当我们创建HttpClient类时,这是可以覆盖的。下面是一个例子:
HttpClient apacheHttpClient = HttpClients.custom()
.setConnectionReuseStrategy(new DefaultConnectionReuseStrategy())
.setConnectionManager(new PoolingHttpClientConnectionManager(r))
.setUserTokenHandler(new UserTokenHandler() {
@Override
public Object getUserToken(HttpContext context) {
return null;
}
})
.build();
Run Code Online (Sandbox Code Playgroud)
DefaultUserTokenHandler如果HttpClient您创建的可以通过相同的 HTTP 路由连接到多个 SSL 对等点,请检查您是否丢失了您依赖的任何内容,并且不要使用此方法。在我的情况下,此客户端用于连接到单个 SSL 服务器。