From 2ac4151c04c845a0ca970e784dcd203750459c3d Mon Sep 17 00:00:00 2001 From: ymlam Date: Thu, 5 Sep 2019 02:42:10 -0400 Subject: [PATCH] Use PoolingHttpClientConnectionManager to handle postback persistent connections to Portal. --- .../java/altk/comm/engine/CommEngine.java | 13 +++- .../altk/comm/engine/postback/PostBack.java | 69 ++++++++++++++++--- 2 files changed, 69 insertions(+), 13 deletions(-) diff --git a/src/main/java/altk/comm/engine/CommEngine.java b/src/main/java/altk/comm/engine/CommEngine.java index 46cf8f0..1c62254 100644 --- a/src/main/java/altk/comm/engine/CommEngine.java +++ b/src/main/java/altk/comm/engine/CommEngine.java @@ -5,6 +5,9 @@ import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.PrintWriter; +import java.security.KeyManagementException; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; import java.util.Enumeration; import java.util.HashMap; import java.util.Map; @@ -587,15 +590,19 @@ public abstract class CommEngine extends HttpServlet */ abstract protected void destroyChild(); - public PostBack getPostBack(String postBackURL, String broadcastType) + public PostBack getPostBack(String postBackURL, String broadcastType) throws BroadcastException { if (postBackURL == null) return null; PostBack postBack = postBackMap.get(postBackURL); if (postBack != null) return postBack; - postBack = new PostBack(postBackURL, broadcastType + "_status", - postbackMaxQueueSize, postbackSenderPoolSize, postbackMaxBatchSize); + try { + postBack = new PostBack(postBackURL, broadcastType + "_status", + postbackMaxQueueSize, postbackSenderPoolSize, postbackMaxBatchSize); + } catch (KeyManagementException | IllegalArgumentException | NoSuchAlgorithmException | KeyStoreException e) { + throw new BroadcastException(BroadcastError.PLATFORM_ERROR, e.getMessage(), e); + } postBackMap.put(postBackURL, postBack); return postBack; } diff --git a/src/main/java/altk/comm/engine/postback/PostBack.java b/src/main/java/altk/comm/engine/postback/PostBack.java index 75796e8..e02bfc8 100644 --- a/src/main/java/altk/comm/engine/postback/PostBack.java +++ b/src/main/java/altk/comm/engine/postback/PostBack.java @@ -21,6 +21,7 @@ import javax.xml.xpath.XPathExpressionException; import javax.xml.xpath.XPathFactory; import org.apache.http.StatusLine; +import org.apache.http.client.HttpRequestRetryHandler; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpPost; import org.apache.http.conn.ssl.NoopHostnameVerifier; @@ -29,7 +30,9 @@ import org.apache.http.conn.ssl.TrustStrategy; import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClientBuilder; +import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; import org.apache.http.protocol.BasicHttpContext; +import org.apache.http.protocol.HttpContext; import org.apache.http.ssl.SSLContextBuilder; import org.apache.http.util.EntityUtils; import org.apache.log4j.Logger; @@ -57,6 +60,8 @@ public class PostBack private static final int QUEUE_WAIT = 300; // seconds private static final int POSTBACK_SERVER_WAIT_TIME = 10; // seconds + + private static final int RETRIES_DEFAULT = 3; private final String postBackURL; private final String xmlTopElement; @@ -66,7 +71,16 @@ public class PostBack private final String myName; private int maxBatchSize; + private PoolingHttpClientConnectionManager cm; private int threadsWaitingToPost; + private TrustStrategy tustAllCerts; + SSLContext sslContext; + SSLConnectionSocketFactory connectionFactory; + CloseableHttpClient httpclient; + + private int maxRetries; + + private static Logger myLogger = Logger.getLogger(PostBack.class); @@ -82,6 +96,7 @@ public class PostBack { private boolean threadShouldStop; + private Sender(String name) { setName(name); @@ -192,16 +207,12 @@ public class PostBack } xml.append(""); - TrustStrategy tustAllCerts = new TrustStrategy() { public boolean isTrusted(X509Certificate[] chain, String authType) { return true; } }; HttpPost httpPost = new HttpPost(postBackURL); StringEntity requestEntity; CloseableHttpResponse response = null; byte[] xmlBytes = null; try { - SSLContext sslContext = SSLContextBuilder.create().loadTrustMaterial(tustAllCerts).build(); - SSLConnectionSocketFactory connectionFactory = new SSLConnectionSocketFactory(sslContext, new NoopHostnameVerifier()); - CloseableHttpClient httpclient = HttpClientBuilder.create().setSSLSocketFactory(connectionFactory).build(); requestEntity = (new StringEntity(xml.toString())); httpPost.setEntity(requestEntity); myLogger.debug("Posting to " + postBackURL + ": " + xml); @@ -224,11 +235,7 @@ public class PostBack CommonLogger.alarm.error("While posting back to broadcast requester: " + e); return PostBackStatus.IRRECOVERABLE_ERROR; } - catch (KeyManagementException | NoSuchAlgorithmException | KeyStoreException e) - { - CommonLogger.alarm.error("Totally unexpected. While constructing HttpClient for posting back to broadcast requester: " + e); - return PostBackStatus.IRRECOVERABLE_ERROR; - } + String xmlStr; try @@ -317,10 +324,13 @@ public class PostBack * @param xmlTopElementName * @throws IllegalArgumentException if either postBackURL or xmlTopElementName is * not supplied nor valid. + * @throws KeyStoreException + * @throws NoSuchAlgorithmException + * @throws KeyManagementException */ public PostBack(String postBackURL, String xmlTopElementName, int maxQueueSize, int senderPoolSize, int maxBatchSize) - throws IllegalArgumentException + throws IllegalArgumentException, KeyManagementException, NoSuchAlgorithmException, KeyStoreException { if (postBackURL == null || postBackURL.length() == 0) { @@ -337,7 +347,36 @@ public class PostBack this.maxBatchSize = maxBatchSize; postQueue = new LinkedList(); threadsWaitingToPost = 0; + cm = new PoolingHttpClientConnectionManager(); + cm.setMaxTotal(senderPoolSize); + cm.setDefaultMaxPerRoute(senderPoolSize); + + tustAllCerts = new TrustStrategy() { public boolean isTrusted(X509Certificate[] chain, String authType) { return true; } }; + + sslContext = SSLContextBuilder.create().loadTrustMaterial(tustAllCerts).build(); + connectionFactory = new SSLConnectionSocketFactory(sslContext, new NoopHostnameVerifier()); + // + // Retry handler + maxRetries = RETRIES_DEFAULT; + HttpRequestRetryHandler retryHandler = new HttpRequestRetryHandler() + { + public boolean retryRequest( + IOException exception, + int executionCount, + HttpContext context) + { + if (executionCount >= maxRetries) return false; + return true; + } + }; + + httpclient = HttpClientBuilder.create() + // .setConnectionManager(cm) + // .setRetryHandler(retryHandler) + .setSSLSocketFactory(connectionFactory) + .build(); + senderPool = new ArrayList(); for (int i = 0; i < senderPoolSize; i++) { @@ -393,6 +432,16 @@ public class PostBack public void terminate() { + try + { + httpclient.close(); + } + catch (IOException e) + { + myLogger.error("Caught when closing HttpClient: " + e.getMessage()); + } + + // Terminate postback threads for (Sender sender : senderPool) { sender.terminate();