From 1ca85017f779c0a89841152f3f182c928e83defc Mon Sep 17 00:00:00 2001 From: Pankaj Date: Tue, 16 Mar 2021 05:15:40 +0530 Subject: [PATCH] HBASE-25374 Make REST Client connection and socket time out configurable (#2752) Signed-off-by: Guanghao Zhang Signed-off-by: stack --- .../apache/hadoop/hbase/rest/Constants.java | 8 +++ .../hadoop/hbase/rest/client/Client.java | 54 +++++++++++++++---- 2 files changed, 53 insertions(+), 9 deletions(-) diff --git a/hbase-rest/src/main/java/org/apache/hadoop/hbase/rest/Constants.java b/hbase-rest/src/main/java/org/apache/hadoop/hbase/rest/Constants.java index 704eac78db5..56bc9297f85 100644 --- a/hbase-rest/src/main/java/org/apache/hadoop/hbase/rest/Constants.java +++ b/hbase-rest/src/main/java/org/apache/hadoop/hbase/rest/Constants.java @@ -89,4 +89,12 @@ public interface Constants { /** If this query parameter is present when processing row or scanner resources, it disables server side block caching */ String NOCACHE_PARAM_NAME = "nocache"; + + /** Configuration parameter to set rest client connection timeout */ + String REST_CLIENT_CONN_TIMEOUT = "hbase.rest.client.conn.timeout"; + int DEFAULT_REST_CLIENT_CONN_TIMEOUT = 2 * 1000; + + /** Configuration parameter to set rest client socket timeout */ + String REST_CLIENT_SOCKET_TIMEOUT = "hbase.rest.client.socket.timeout"; + int DEFAULT_REST_CLIENT_SOCKET_TIMEOUT = 30 * 1000; } diff --git a/hbase-rest/src/main/java/org/apache/hadoop/hbase/rest/client/Client.java b/hbase-rest/src/main/java/org/apache/hadoop/hbase/rest/client/Client.java index 76f8ab151da..05a4cacfa0a 100644 --- a/hbase-rest/src/main/java/org/apache/hadoop/hbase/rest/client/Client.java +++ b/hbase-rest/src/main/java/org/apache/hadoop/hbase/rest/client/Client.java @@ -40,6 +40,10 @@ import java.util.Map; import java.util.Optional; import java.util.concurrent.ConcurrentHashMap; import javax.net.ssl.SSLContext; + +import org.apache.hadoop.conf.Configuration; +import org.apache.hadoop.hbase.HBaseConfiguration; +import org.apache.hadoop.hbase.rest.Constants; import org.apache.hadoop.security.authentication.client.AuthenticatedURL; import org.apache.hadoop.security.authentication.client.AuthenticationException; import org.apache.hadoop.security.authentication.client.KerberosAuthenticator; @@ -76,6 +80,7 @@ public class Client { private HttpClient httpClient; private Cluster cluster; + private Configuration conf; private boolean sslEnabled; private HttpResponse resp; private HttpGet httpGet = null; @@ -93,16 +98,22 @@ public class Client { this(null); } - private void initialize(Cluster cluster, boolean sslEnabled, Optional trustStore) { + private void initialize(Cluster cluster, Configuration conf, boolean sslEnabled, + Optional trustStore) { this.cluster = cluster; + this.conf = conf; this.sslEnabled = sslEnabled; extraHeaders = new ConcurrentHashMap<>(); String clspath = System.getProperty("java.class.path"); LOG.debug("classpath " + clspath); HttpClientBuilder httpClientBuilder = HttpClients.custom(); - RequestConfig requestConfig = RequestConfig.custom(). - setConnectTimeout(2000).build(); + int connTimeout = this.conf.getInt(Constants.REST_CLIENT_CONN_TIMEOUT, + Constants.DEFAULT_REST_CLIENT_CONN_TIMEOUT); + int socketTimeout = this.conf.getInt(Constants.REST_CLIENT_SOCKET_TIMEOUT, + Constants.DEFAULT_REST_CLIENT_SOCKET_TIMEOUT); + RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(connTimeout) + .setSocketTimeout(socketTimeout).build(); httpClientBuilder.setDefaultRequestConfig(requestConfig); // Since HBASE-25267 we don't use the deprecated DefaultHttpClient anymore. @@ -138,7 +149,17 @@ public class Client { * @param sslEnabled enable SSL or not */ public Client(Cluster cluster, boolean sslEnabled) { - initialize(cluster, sslEnabled, Optional.empty()); + initialize(cluster, HBaseConfiguration.create(), sslEnabled, Optional.empty()); + } + + /** + * Constructor + * @param cluster the cluster definition + * @param conf Configuration + * @param sslEnabled enable SSL or not + */ + public Client(Cluster cluster, Configuration conf, boolean sslEnabled) { + initialize(cluster, conf, sslEnabled, Optional.empty()); } /** @@ -151,8 +172,23 @@ public class Client { * * @throws ClientTrustStoreInitializationException if the trust store file can not be loaded */ - public Client(Cluster cluster, String trustStorePath, - Optional trustStorePassword, Optional trustStoreType) { + public Client(Cluster cluster, String trustStorePath, Optional trustStorePassword, + Optional trustStoreType) { + this(cluster, HBaseConfiguration.create(), trustStorePath, trustStorePassword, trustStoreType); + } + + /** + * Constructor, allowing to define custom trust store (only for SSL connections) + * + * @param cluster the cluster definition + * @param conf Configuration + * @param trustStorePath custom trust store to use for SSL connections + * @param trustStorePassword password to use for custom trust store + * @param trustStoreType type of custom trust store + * @throws ClientTrustStoreInitializationException if the trust store file can not be loaded + */ + public Client(Cluster cluster, Configuration conf, String trustStorePath, + Optional trustStorePassword, Optional trustStoreType) { char[] password = trustStorePassword.map(String::toCharArray).orElse(null); String type = trustStoreType.orElse(KeyStore.getDefaultType()); @@ -163,15 +199,15 @@ public class Client { } catch (KeyStoreException e) { throw new ClientTrustStoreInitializationException("Invalid trust store type: " + type, e); } - try (InputStream inputStream = - new BufferedInputStream(Files.newInputStream(new File(trustStorePath).toPath()))) { + try (InputStream inputStream = new BufferedInputStream( + Files.newInputStream(new File(trustStorePath).toPath()))) { trustStore.load(inputStream, password); } catch (CertificateException | NoSuchAlgorithmException | IOException e) { throw new ClientTrustStoreInitializationException("Trust store load error: " + trustStorePath, e); } - initialize(cluster, true, Optional.of(trustStore)); + initialize(cluster, conf, true, Optional.of(trustStore)); } /**