diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/RSRpcServices.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/RSRpcServices.java index 9c1dfbba1e2..71711343e4f 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/RSRpcServices.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/RSRpcServices.java @@ -41,6 +41,7 @@ import java.util.Set; import java.util.TreeSet; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.ThreadLocalRandom; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicLong; @@ -316,6 +317,10 @@ public class RSRpcServices implements HBaseRPCErrorHandler, */ private static final boolean DEFAULT_REJECT_BATCH_ROWS_OVER_THRESHOLD = false; + public static final String CLIENT_BOOTSTRAP_NODE_LIMIT = "hbase.client.bootstrap.node.limit"; + + public static final int DEFAULT_CLIENT_BOOTSTRAP_NODE_LIMIT = 10; + // Request counter. (Includes requests that are not serviced by regions.) // Count only once for requests with multiple actions like multi/caching-scan/replayBatch final LongAdder requestCount = new LongAdder(); @@ -4068,8 +4073,12 @@ public class RSRpcServices implements HBaseRPCErrorHandler, @Override public final GetBootstrapNodesResponse getBootstrapNodes(RpcController controller, GetBootstrapNodesRequest request) throws ServiceException { + List bootstrapNodes = new ArrayList<>(regionServer.getRegionServers()); + Collections.shuffle(bootstrapNodes, ThreadLocalRandom.current()); + int maxNodeCount = regionServer.getConfiguration().getInt(CLIENT_BOOTSTRAP_NODE_LIMIT, + DEFAULT_CLIENT_BOOTSTRAP_NODE_LIMIT); GetBootstrapNodesResponse.Builder builder = GetBootstrapNodesResponse.newBuilder(); - regionServer.getRegionServers().stream().map(ProtobufUtil::toServerName) + bootstrapNodes.stream().limit(maxNodeCount).map(ProtobufUtil::toServerName) .forEach(builder::addServerName); return builder.build(); } diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestRpcConnectionRegistry.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestRpcConnectionRegistry.java index 20e77a8181b..6fd988e3982 100644 --- a/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestRpcConnectionRegistry.java +++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestRpcConnectionRegistry.java @@ -31,6 +31,7 @@ import org.apache.hadoop.hbase.HRegionLocation; import org.apache.hadoop.hbase.ServerName; import org.apache.hadoop.hbase.TableName; import org.apache.hadoop.hbase.master.HMaster; +import org.apache.hadoop.hbase.regionserver.RSRpcServices; import org.apache.hadoop.hbase.testclassification.ClientTests; import org.apache.hadoop.hbase.testclassification.MediumTests; import org.junit.After; @@ -78,6 +79,15 @@ public class TestRpcConnectionRegistry { Closeables.close(registry, true); } + private void setMaxNodeCount(int count) { + UTIL.getMiniHBaseCluster().getMasterThreads().stream() + .map(t -> t.getMaster().getConfiguration()) + .forEach(conf -> conf.setInt(RSRpcServices.CLIENT_BOOTSTRAP_NODE_LIMIT, count)); + UTIL.getMiniHBaseCluster().getRegionServerThreads().stream() + .map(t -> t.getRegionServer().getConfiguration()) + .forEach(conf -> conf.setInt(RSRpcServices.CLIENT_BOOTSTRAP_NODE_LIMIT, count)); + } + @Test public void testRegistryRPCs() throws Exception { HMaster activeMaster = UTIL.getHBaseCluster().getMaster(); @@ -99,5 +109,9 @@ public class TestRpcConnectionRegistry { Collections.sort(metaLocations); Collections.sort(actualMetaLocations); assertEquals(actualMetaLocations, metaLocations); + + // test that the node count config works + setMaxNodeCount(1); + UTIL.waitFor(10000, () -> registry.getParsedServers().size() == 1); } }