Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

HBASE-28500 Rest Java client library assumes stateless servers #5804

Merged
merged 1 commit into from
Apr 16, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -249,10 +251,12 @@ public void removeExtraHeader(final String name) {
}

/**
* 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
Expand All @@ -265,10 +269,12 @@ public HttpResponse executePathOnly(Cluster cluster, HttpUriRequest method, Head
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) {
Expand Down Expand Up @@ -302,7 +308,11 @@ public HttpResponse executePathOnly(Cluster cluster, HttpUriRequest method, Head
} 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;
}

Expand Down Expand Up @@ -406,6 +416,28 @@ public void setCluster(Cluster cluster) {
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
Expand Down