You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@helix.apache.org by hz...@apache.org on 2020/10/16 22:35:15 UTC

[helix] branch master updated: Fix connection leakage in CustomRestClient (#1472)

This is an automated email from the ASF dual-hosted git repository.

hzlu pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/helix.git


The following commit(s) were added to refs/heads/master by this push:
     new c3515f4  Fix connection leakage in CustomRestClient (#1472)
c3515f4 is described below

commit c3515f4e05466580b2acaaea79bebbf21b1b1e58
Author: Huizhi Lu <ih...@gmail.com>
AuthorDate: Fri Oct 16 15:35:02 2020 -0700

    Fix connection leakage in CustomRestClient (#1472)
    
    There is connection leakage in CustomRestClientImpl and causes timeout waiting for connection.
    Fix this issue by consuming entity and releasing the content stream and connection.
---
 .../apache/helix/rest/client/CustomRestClientImpl.java  | 17 ++++++++++++++---
 1 file changed, 14 insertions(+), 3 deletions(-)

diff --git a/helix-rest/src/main/java/org/apache/helix/rest/client/CustomRestClientImpl.java b/helix-rest/src/main/java/org/apache/helix/rest/client/CustomRestClientImpl.java
index cb6b3ee..c7b5ac4 100644
--- a/helix-rest/src/main/java/org/apache/helix/rest/client/CustomRestClientImpl.java
+++ b/helix-rest/src/main/java/org/apache/helix/rest/client/CustomRestClientImpl.java
@@ -40,7 +40,7 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 class CustomRestClientImpl implements CustomRestClient {
-  private static final Logger LOG = LoggerFactory.getLogger(CustomRestClient.class);
+  private static final Logger LOG = LoggerFactory.getLogger(CustomRestClientImpl.class);
 
   // postfix used to append at the end of base url
   private static final String INSTANCE_HEALTH_STATUS = "/instanceHealthStatus";
@@ -116,6 +116,8 @@ class CustomRestClientImpl implements CustomRestClient {
       LOG.info("Expected HttpResponse statusCode: {}", HttpStatus.SC_OK);
       return jsonConverter.convert(getJsonObject(httpResponse));
     } else {
+      // Ensure entity is fully consumed so stream is closed.
+      EntityUtils.consumeQuietly(httpResponse.getEntity());
       throw new ClientProtocolException("Unexpected response status: " + status + ", reason: "
           + httpResponse.getStatusLine().getReasonPhrase());
     }
@@ -123,18 +125,27 @@ class CustomRestClientImpl implements CustomRestClient {
 
   @VisibleForTesting
   protected HttpResponse post(String url, Map<String, String> payloads) throws IOException {
+    HttpPost postRequest = new HttpPost(url);
     try {
-      HttpPost postRequest = new HttpPost(url);
       postRequest.setHeader("Accept", ACCEPT_CONTENT_TYPE);
       StringEntity entity = new StringEntity(OBJECT_MAPPER.writeValueAsString(payloads),
           ContentType.APPLICATION_JSON);
       postRequest.setEntity(entity);
       LOG.info("Executing request: {}, headers: {}, entity: {}", postRequest.getRequestLine(),
           postRequest.getAllHeaders(), postRequest.getEntity());
-      return _httpClient.execute(postRequest);
+
+      HttpResponse response = _httpClient.execute(postRequest);
+      int status = response.getStatusLine().getStatusCode();
+      if (status != HttpStatus.SC_OK) {
+        LOG.warn("Received non-200 status code: {}, payloads: {}", status, payloads);
+      }
+
+      return response;
     } catch (IOException e) {
       LOG.error("Failed to perform customized health check. Is participant endpoint {} available?",
           url, e);
+      // Release connection to be reused and avoid connection leakage.
+      postRequest.releaseConnection();
       throw e;
     }
   }