You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hbase.apache.org by st...@apache.org on 2024/04/16 07:20:24 UTC
(hbase) branch branch-3 updated: HBASE-28500 Rest Java client library assumes stateless servers (#5804)
This is an automated email from the ASF dual-hosted git repository.
stoty pushed a commit to branch branch-3
in repository https://gitbox.apache.org/repos/asf/hbase.git
The following commit(s) were added to refs/heads/branch-3 by this push:
new d72ef08fd0a HBASE-28500 Rest Java client library assumes stateless servers (#5804)
d72ef08fd0a is described below
commit d72ef08fd0a0c28c30677371d6192658ddd65adf
Author: Istvan Toth <st...@apache.org>
AuthorDate: Tue Apr 16 09:16:05 2024 +0200
HBASE-28500 Rest Java client library assumes stateless servers (#5804)
add a sticky flag which forces using the same server for all requests
Signed-off-by: Peter Somogyi <ps...@apache.org>
Signed-off-by: Duo Zhang <zh...@apache.org>
---
.../apache/hadoop/hbase/rest/client/Client.java | 48 ++++++++++++++++++----
1 file changed, 40 insertions(+), 8 deletions(-)
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 9283cb94a7e..96cb5f290b0 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
@@ -79,6 +79,8 @@ public class Client {
private HttpClient httpClient;
private Cluster cluster;
+ private Integer lastNodeId;
+ private boolean sticky = false;
private Configuration conf;
private boolean sslEnabled;
private HttpResponse resp;
@@ -249,10 +251,12 @@ public class Client {
}
/**
- * Execute a transaction method given only the path. Will select at random one of the members of
- * the supplied cluster definition and iterate through the list until a transaction can be
- * successfully completed. The definition of success here is a complete HTTP transaction,
- * irrespective of result code.
+ * Execute a transaction method given only the path. If sticky is false: Will select at random one
+ * of the members of the supplied cluster definition and iterate through the list until a
+ * transaction can be successfully completed. The definition of success here is a complete HTTP
+ * transaction, irrespective of result code. If sticky is true: For the first request it will
+ * select a random one of the members of the supplied cluster definition. For subsequent requests
+ * it will use the same member, and it will not automatically re-try if the call fails.
* @param cluster the cluster definition
* @param method the transaction method
* @param headers HTTP header values to send
@@ -265,10 +269,12 @@ public class Client {
if (cluster.nodes.size() < 1) {
throw new IOException("Cluster is empty");
}
- int start = (int) Math.round((cluster.nodes.size() - 1) * Math.random());
- int i = start;
+ if (lastNodeId == null || !sticky) {
+ lastNodeId = (int) (cluster.nodes.size() * Math.random());
+ }
+ int start = lastNodeId;
do {
- cluster.lastHost = cluster.nodes.get(i);
+ cluster.lastHost = cluster.nodes.get(lastNodeId);
try {
StringBuilder sb = new StringBuilder();
if (sslEnabled) {
@@ -302,7 +308,11 @@ public class Client {
} catch (URISyntaxException use) {
lastException = new IOException(use);
}
- } while (++i != start && i < cluster.nodes.size());
+ if (!sticky) {
+ lastNodeId = (++lastNodeId) % cluster.nodes.size();
+ }
+ // Do not retry if sticky. Let the caller handle the error.
+ } while (!sticky && lastNodeId != start);
throw lastException;
}
@@ -406,6 +416,28 @@ public class Client {
this.cluster = cluster;
}
+ /**
+ * The default behaviour is load balancing by sending each request to a random host. This DOES NOT
+ * work with scans, which have state on the REST servers. Make sure sticky is set to true before
+ * attempting Scan related operations if more than one host is defined in the cluster.
+ * @return whether subsequent requests will use the same host
+ */
+ public boolean isSticky() {
+ return sticky;
+ }
+
+ /**
+ * The default behaviour is load balancing by sending each request to a random host. This DOES NOT
+ * work with scans, which have state on the REST servers. Set sticky to true before attempting
+ * Scan related operations if more than one host is defined in the cluster. Nodes must not be
+ * added or removed from the Cluster object while sticky is true.
+ * @param sticky whether subsequent requests will use the same host
+ */
+ public void setSticky(boolean sticky) {
+ lastNodeId = null;
+ this.sticky = sticky;
+ }
+
/**
* Send a HEAD request
* @param path the path or URI