通过java连接kvstore连接池,Java,HttpClient4.5,https及使用连接池

论坛 期权论坛 编程之家     
选择匿名的用户   2021-5-26 12:13   11   0

技术环境:

idea2019 + maven3.6 + Java8 + httpclient4.5

连接池参数说明:

maxTotal,最大连接数===>连接池里的最大连接数;

connectTimeout,连接超时==>指客户端和服务器建立连接的timeout;

socketTimeout,读超时===>客户端和服务器建立连接后,客户端从服务器读取数据的timeout,超出后会抛出SocketTimeOutException;

connectionRequestTimeout,请求超时==>指从连接池获取连接的timeout;

defaultMaxPerRoute、maxPerRoute,每次能并行接收的请求数量===>某一个/每服务每次能并行接收的请求数量,这里route指的是域名;

retryCount,重试次数;

requestSentRetryEnabled,请求失败是否重发;

evictIdleConnections,移除空闲连接时间;

共享代码:

pom.xml

org.apache.httpcomponents httpclient 4.5.13 org.apache.httpcomponents httpmime 4.5.13 org.apache.httpcomponents httpasyncclient 4.1

HttpConnectionPoolManager(连接池类):

import org.apache.http.HttpHost;import org.apache.http.client.HttpRequestRetryHandler;import org.apache.http.client.config.RequestConfig;import org.apache.http.config.Registry;import org.apache.http.config.RegistryBuilder;import org.apache.http.conn.HttpClientConnectionManager;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.SSLConnectionSocketFactory;import org.apache.http.impl.client.CloseableHttpClient;import org.apache.http.impl.client.DefaultHttpRequestRetryHandler;import org.apache.http.impl.client.HttpClients;import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;import org.springframework.util.StringUtils;import javax.net.ssl.SSLContext;import java.util.Properties;import java.util.concurrent.TimeUnit;public final class HttpConnectionPoolManager { private Properties props; private String hostname; private int port; private PoolingHttpClientConnectionManager httpClientConnectionManager; private IdleConnectionEvictor idleConnectionEvictor; /** * @param hostname * @param port */ public HttpConnectionPoolManager(String hostname, int port) { this.hostname = hostname; this.port = port; props = new Properties(); //==================================================================================================// // 最大连接数===>连接池里的最大连接数 //==================================================================================================// props.setProperty("maxTotal", String.valueOf(20)); //==================================================================================================// // 连接超时==>指客户端和服务器建立连接的timeout //==================================================================================================// props.setProperty("connectTimeout", String.valueOf(60 * 1000)); //==================================================================================================// // 读超时===>客户端和服务器建立连接后,客户端从服务器读取数据的timeout,超出后会抛出SocketTimeOutException //==================================================================================================// props.setProperty("socketTimeout", String.valueOf(30 * 1000)); //==================================================================================================// // 请求超时==>指从连接池获取连接的timeout //==================================================================================================// props.setProperty("connectionRequestTimeout", String.valueOf(10 * 1000)); //==================================================================================================// // 每次能并行接收的请求数量===>某一个/每服务每次能并行接收的请求数量,这里route指的是域名 //==================================================================================================// props.setProperty("defaultMaxPerRoute", String.valueOf(40)); props.setProperty("maxPerRoute", String.valueOf(60)); //==================================================================================================// // 重试次数、请求失败是否重发 //==================================================================================================// props.setProperty("retryCount", String.valueOf(3)); props.setProperty("requestSentRetryEnabled", String.valueOf(false)); //==================================================================================================// // 移除空闲连接时间 //==================================================================================================// props.setProperty("evictIdleConnections", String.valueOf(30 * 10000)); } /** * @param props * @param hostname * @param port */ public HttpConnectionPoolManager(Properties props, String hostname, int port) { this.props = props; this.hostname = hostname; this.port = port; } /** * @return */ private PoolingHttpClientConnectionManager getConnectionManager() { if (httpClientConnectionManager == null) { synchronized (this) { if (httpClientConnectionManager == null) { httpClientConnectionManager = createConnectionManager(); } } } return httpClientConnectionManager; } /** * @return */ private Registry createSocketFactoryRegistry() { SSLContext sslContext = MySSLContextUtils.createDefaultSSLContext(); Registry socketFactoryRegistry = RegistryBuilder .create() .register("http", PlainConnectionSocketFactory.INSTANCE) .register("https", new SSLConnectionSocketFactory(sslContext)) .build(); return socketFactoryRegistry; } /** * @return */ private PoolingHttpClientConnectionManager createConnectionManager() { PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(createSocketFactoryRegistry()); connectionManager.setMaxTotal(getIntProperty("maxTotal", 20)); connectionManager.setDefaultMaxPerRoute(getIntProperty("defaultMaxPerRoute", 40)); HttpHost httpHost = new HttpHost(hostname, port); HttpRoute httpRoute = new HttpRoute(httpHost); connectionManager.setMaxPerRoute(httpRoute, getIntProperty("maxPerRoute", 40)); // 清理无效连接 idleConnectionEvictor = new IdleConnectionEvictor(connectionManager); idleConnectionEvictor.setName("httpclient-connection-" + httpHost.toString() + "-idle-thread"); idleConnectionEvictor.setDaemon(true); idleConnectionEvictor.start(); return connectionManager; } /** * @return */ public CloseableHttpClient getDefaultCustomClient() { int connectTimeoutMillisecond = getIntProperty("connectTimeout", 60 * 1000); int socketTimeoutMillisecond = getIntProperty("socketTimeout", 30 * 1000); int connectionRequestTimeoutMillisecond = getIntProperty("connectionRequestTimeout", 10 * 1000); int retryCount = getIntProperty("retryCount", 3); boolean requestSentRetryEnabled = getBoolProperty("requestSentRetryEnabled", false); int evictIdleConnectionsMillisecond = getIntProperty("evictIdleConnections", 30 * 10000); return getCustomClient(connectTimeoutMillisecond, socketTimeoutMillisecond, connectionRequestTimeoutMillisecond, retryCount, requestSentRetryEnabled, evictIdleConnectionsMillisecond); } /** * @param name * @param defaultValue * @return */ private int getIntProperty(String name, int defaultValue) { String value = props.getProperty(name, String.valueOf(defaultValue)); if (!StringUtils.isEmpty(value)) { return Integer.parseInt(value); } return defaultValue; } /** * @param name * @param defaultValue * @return */ private boolean getBoolProperty(String name, boolean defaultValue) { String value = props.getProperty(name, String.valueOf(defaultValue)); if (!StringUtils.isEmpty(value)) { return Boolean.parseBoolean(value); } return defaultValue; } /** * @param connectTimeoutMillisecond * @param socketTimeoutMillisecond * @param connectionRequestTimeoutMillisecond * @param retryCount * @param requestSentRetryEnabled * @param evictIdleConnectionsMillisecond * @return */ public CloseableHttpClient getCustomClient(int connectTimeoutMillisecond, int socketTimeoutMillisecond, int connectionRequestTimeoutMillisecond, int retryCount, boolean requestSentRetryEnabled, int evictIdleConnectionsMillisecond) { //默认连接配置 RequestConfig defaultRequestConfig = RequestConfig.custom() .setConnectTimeout(connectTimeoutMillisecond) .setSocketTimeout(socketTimeoutMillisecond) .setConnectionRequestTimeout(connectionRequestTimeoutMillisecond) .build(); // retryCount==>重试次数, requestSentRetryEnabled==>允许请求重发 HttpRequestRetryHandler httpRetryHandler = new DefaultHttpRequestRetryHandler(retryCount, requestSentRetryEnabled); return HttpClients.custom() .setDefaultRequestConfig(defaultRequestConfig) .evictExpiredConnections() .setConnectionManagerShared(false) .evictIdleConnections(evictIdleConnectionsMillisecond, TimeUnit.MILLISECONDS) .setConnectionManager(getConnectionManager()) .setRetryHandler(httpRetryHandler).build(); } /** * 监听连接池中空闲连接,清理无效连接 */ class IdleConnectionEvictor extends Thread { private final HttpClientConnectionManager connectionManager; private volatile boolean shutdown; public IdleConnectionEvictor(HttpClientConnectionManager connectionManager) { this.connectionManager = connectionManager; } @Override public void run() { try { while (!shutdown) { synchronized (this) { //3s检查一次 this.wait(3000); // 关闭失效的连接 connectionManager.closeExpiredConnections(); } } } catch (InterruptedException ex) { ex.printStackTrace(); } } public void shutdown() { shutdown = true; synchronized (this) { notifyAll(); } } } /** * 关闭连接池 */ public void shutdownConnectionManager() { if (idleConnectionEvictor != null) { idleConnectionEvictor.shutdown(); idleConnectionEvictor = null; } if (httpClientConnectionManager != null) { httpClientConnectionManager.shutdown(); httpClientConnectionManager = null; } }}

SSLContext工具类:

import org.apache.http.conn.ssl.TrustSelfSignedStrategy;import org.apache.http.ssl.SSLContexts;import javax.net.ssl.SSLContext;import javax.net.ssl.TrustManager;import javax.net.ssl.X509TrustManager;import java.io.File;import java.io.FileInputStream;import java.io.InputStream;import java.security.KeyManagementException;import java.security.KeyStore;import java.security.NoSuchAlgorithmException;import java.security.cert.Certificate;import java.security.cert.CertificateException;import java.security.cert.X509Certificate;public final class MySSLContextUtils { /** * @return */ public static SSLContext createDefaultSSLContext() { if (false) { // 单向认证,随意的证书与服务端可信交互,连接建立后,协商使用对称加密算法通信 return createGenerateSSLContext(); } else if (false) { // 单向认证,随意的证书与服务端可信交互,连接建立后,协商使用对称加密算法通信 return createKeystoreSSLContext(); } else { // 双向认证,服务端验证客户端证书(从证书可中获取传递),客户端验证服务端证书(代码中验证) return createKeystoreAliasSSLContext(); } } /** * @return */ private static SSLContext createGenerateSSLContext() { SSLContext sslContext = null; try { sslContext = SSLContext.getInstance("SSL"); TrustManager[] trustAllCerts = new TrustManager[]{new X509TrustManager() { @Override public void checkClientTrusted(java.security.cert.X509Certificate[] x509Certificates, String s) throws CertificateException { } @Override public void checkServerTrusted(java.security.cert.X509Certificate[] x509Certificates, String s) throws CertificateException { } @Override public java.security.cert.X509Certificate[] getAcceptedIssuers() { return null; } }}; sslContext.init(null, trustAllCerts, new java.security.SecureRandom()); } catch (KeyManagementException e) { e.printStackTrace(); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } return sslContext; } /** * @return */ public static SSLContext createKeystoreSSLContext() { File keystoreFile = new File("D:\\client.jks"); String keystorePassword = "123456"; return createSSLContext(keystoreFile, keystorePassword); } /** * keytool -genkey -dname "CN=XFDClient,OU=XFDUnit,O=XFD,L=TaiYuan, ST=ShanXi, C=CN" -keysize 2048 -alias client -keyalg RSA -keystore d:/client.jks -keypass 123456 -storepass 123456 -validity 36500 * * @param keystoreFile * @param keystorePassword * @return */ public static SSLContext createSSLContext(File keystoreFile, String keystorePassword) { SSLContext sslcontext = null; try { // 设置truststore KeyStore trustStore = KeyStore.getInstance("JKS"); InputStream keystoreInput = new FileInputStream(keystoreFile); try { trustStore.load(keystoreInput, keystorePassword.toCharArray()); } finally { try { keystoreInput.close(); } catch (Exception ignore) { } } sslcontext = SSLContexts.custom().loadTrustMaterial(trustStore, new TrustSelfSignedStrategy()).build(); // 创建TrustManager(空的) X509TrustManager trustManager = new X509TrustManager() { public void checkClientTrusted(X509Certificate[] chain, String authenType) throws CertificateException { // 检查客户端证书 } public void checkServerTrusted(X509Certificate[] chain, String authenType) throws CertificateException { // 检查服务器端证书 } public X509Certificate[] getAcceptedIssuers() { // 返回受信任的X509证书数组 return new java.security.cert.X509Certificate[0]; } }; sslcontext.init(null, new TrustManager[]{trustManager}, null); } catch (Exception e) { e.printStackTrace(); } return sslcontext; } /** * @return */ public static SSLContext createKeystoreAliasSSLContext() { File keystoreFile = new File("D:\\client.jks"); String keystorePassword = "123456"; String alias = "client"; return createSSLContext(keystoreFile, keystorePassword, alias); } /** * keytool -genkey -dname "CN=XFDClient,OU=XFDUnit,O=XFD,L=TaiYuan, ST=ShanXi, C=CN" -keysize 2048 -alias client -keyalg RSA -keystore d:/client.jks -keypass 123456 -storepass 123456 -validity 36500 * * @param keystoreFile * @param keystorePassword * @return */ public static SSLContext createSSLContext(File keystoreFile, String keystorePassword, String alias) { SSLContext sslcontext = null; try { // 设置truststore KeyStore trustStore = KeyStore.getInstance("JKS"); InputStream keystoreInput = new FileInputStream(keystoreFile); try { trustStore.load(keystoreInput, keystorePassword.toCharArray()); } finally { try { keystoreInput.close(); } catch (Exception ignore) { } } sslcontext = SSLContexts.custom().loadTrustMaterial(trustStore, new TrustSelfSignedStrategy()).build(); // 从证书库中根据alias获取证书链 Certificate[] certificates = trustStore.getCertificateChain(alias); // 转换成X509Certificate X509Certificate[] x509Certificates = new X509Certificate[certificates.length]; for (int i = 0; i < certificates.length; i++) { x509Certificates[i] = (X509Certificate) certificates[i]; } // 创建TrustManager(空的) X509TrustManager trustManager = new X509TrustManager() { public void checkClientTrusted(X509Certificate[] chain, String authenType) throws CertificateException { // 检查客户端证书 System.out.println("客户端证书 = " + authenType); } public void checkServerTrusted(X509Certificate[] chain, String authenType) throws CertificateException { // 检查服务器端证书 System.out.println("服务器端证书 = " + authenType); } public X509Certificate[] getAcceptedIssuers() { // 返回受信任的X509证书数组 return x509Certificates; } }; sslcontext.init(null, new TrustManager[]{trustManager}, null); } catch (Exception e) { e.printStackTrace(); } return sslcontext; }}

证书生成,参考地址:

1、Java,安全,自签名证书、Java代码实现颁发数字证书

2、Java,安全,使用Java代码生成数字证书、读取公和私钥

测试类:

import com.alibaba.fastjson.JSON;import org.apache.http.HttpEntity;import org.apache.http.client.methods.CloseableHttpResponse;import org.apache.http.client.methods.HttpPost;import org.apache.http.entity.StringEntity;import org.apache.http.impl.client.CloseableHttpClient;import org.apache.http.impl.client.HttpClients;import org.apache.http.util.EntityUtils;import java.io.IOException;import java.util.HashMap;import java.util.Map;public class HttpConnectionPoolManagerDemo { public static void main(String[] args) { String host = "www.sxmfyy.com"; int port = 443; HttpConnectionPoolManager poolManager = new HttpConnectionPoolManager(host, port); // 调用URL String url = "https://www.xxxxxx.com/api/auth/login"; // 请求参数 Map requestJsonMap = new HashMap<>(); requestJsonMap.put("username","admin"); requestJsonMap.put("password","xxxxxx"); String requestJson = JSON.toJSONString(requestJsonMap); // CloseableHttpClient httpClient = poolManager.getDefaultCustomClient(); HttpPost httpPost = new HttpPost(url); // httpPost.addHeader("Authorization", ""); StringEntity requestEntity = new StringEntity(requestJson, "UTF-8"); requestEntity.setContentType("application/json"); httpPost.setEntity(requestEntity); CloseableHttpResponse response = null; String responseJson = ""; try { response = httpClient.execute(httpPost); HttpEntity responseEntity = response.getEntity(); System.out.println("statusLine=>" + response.getStatusLine()); responseJson = EntityUtils.toString(responseEntity, "UTF-8"); } catch (IOException e) { e.printStackTrace(); } System.out.println("responseJson=>" + responseJson); // 关闭 poolManager.shutdownConnectionManager(); }}

分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:3875789
帖子:775174
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP