This is an automated email from the ASF dual-hosted git repository.
zhangduo pushed a commit to branch branch-2.5
in repository https://gitbox.apache.org/repos/asf/hbase.git
The following commit(s) were added to refs/heads/branch-2.5 by this push:
new bba2eda1a1c HBASE-28913 LoadBalancerPerformanceEvaluation fails with
NPE (#7789) (#7799)
bba2eda1a1c is described below
commit bba2eda1a1cf590f60fb48585e124b06bec8a8a1
Author: Liu Xiao <[email protected]>
AuthorDate: Thu Feb 26 15:08:27 2026 +0800
HBASE-28913 LoadBalancerPerformanceEvaluation fails with NPE (#7789) (#7799)
Signed-off-by: Duo Zhang <[email protected]>
---
.../master/balancer/StochasticLoadBalancer.java | 9 +-
.../LoadBalancerPerformanceEvaluation.java | 25 ++++--
.../TestLoadBalancerPerformanceEvaluation.java | 98 ++++++++++++++++++++++
3 files changed, 122 insertions(+), 10 deletions(-)
diff --git
a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/balancer/StochasticLoadBalancer.java
b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/balancer/StochasticLoadBalancer.java
index 1237d2c899d..ee5475d6fe6 100644
---
a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/balancer/StochasticLoadBalancer.java
+++
b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/balancer/StochasticLoadBalancer.java
@@ -282,10 +282,11 @@ public class StochasticLoadBalancer extends
BaseLoadBalancer {
this.namedQueueRecorder = NamedQueueRecorder.getInstance(conf);
}
- LOG.info("Loaded config; maxSteps=" + maxSteps + ", runMaxSteps=" +
runMaxSteps
- + ", stepsPerRegion=" + stepsPerRegion + ", maxRunningTime=" +
maxRunningTime + ", isByTable="
- + isByTable + ", CostFunctions=" +
Arrays.toString(getCostFunctionNames())
- + " , sum of multiplier of cost functions = " + sumMultiplier + " etc.");
+ LOG.info(
+ "Loaded config: maxSteps={}, runMaxSteps={}, stepsPerRegion={},
maxRunningTime={}, "
+ + "isByTable={}, CostFunctions={}, sum of multiplier of cost functions
= {} etc.",
+ maxSteps, runMaxSteps, stepsPerRegion, maxRunningTime, isByTable,
+ Arrays.toString(getCostFunctionNames()), sumMultiplier);
}
@Override
diff --git
a/hbase-server/src/test/java/org/apache/hadoop/hbase/master/balancer/LoadBalancerPerformanceEvaluation.java
b/hbase-server/src/test/java/org/apache/hadoop/hbase/master/balancer/LoadBalancerPerformanceEvaluation.java
index d5c66828bb2..0058fff02f7 100644
---
a/hbase-server/src/test/java/org/apache/hadoop/hbase/master/balancer/LoadBalancerPerformanceEvaluation.java
+++
b/hbase-server/src/test/java/org/apache/hadoop/hbase/master/balancer/LoadBalancerPerformanceEvaluation.java
@@ -17,6 +17,9 @@
*/
package org.apache.hadoop.hbase.master.balancer;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
@@ -32,6 +35,7 @@ import org.apache.hadoop.hbase.TableName;
import org.apache.hadoop.hbase.client.RegionInfo;
import org.apache.hadoop.hbase.client.RegionInfoBuilder;
import org.apache.hadoop.hbase.master.LoadBalancer;
+import org.apache.hadoop.hbase.master.MasterServices;
import org.apache.hadoop.hbase.util.AbstractHBaseTool;
import org.apache.hadoop.hbase.util.Bytes;
import org.apache.yetus.audience.InterfaceAudience;
@@ -57,16 +61,16 @@ public class LoadBalancerPerformanceEvaluation extends
AbstractHBaseTool {
protected static final HBaseCommonTestingUtility UTIL = new
HBaseCommonTestingUtility();
private static final int DEFAULT_NUM_REGIONS = 1000000;
- private static Option NUM_REGIONS_OPT = new Option("regions", true,
+ private static final Option NUM_REGIONS_OPT = new Option("regions", true,
"Number of regions to consider by load balancer. Default: " +
DEFAULT_NUM_REGIONS);
private static final int DEFAULT_NUM_SERVERS = 1000;
- private static Option NUM_SERVERS_OPT = new Option("servers", true,
+ private static final Option NUM_SERVERS_OPT = new Option("servers", true,
"Number of servers to consider by load balancer. Default: " +
DEFAULT_NUM_SERVERS);
private static final String DEFAULT_LOAD_BALANCER =
"org.apache.hadoop.hbase.master.balancer.StochasticLoadBalancer";
- private static Option LOAD_BALANCER_OPT = new Option("load_balancer", true,
+ private static final Option LOAD_BALANCER_OPT = new Option("load_balancer",
true,
"Type of Load Balancer to use. Default: " + DEFAULT_LOAD_BALANCER);
private int numRegions;
@@ -87,6 +91,15 @@ public class LoadBalancerPerformanceEvaluation extends
AbstractHBaseTool {
conf.setClass(HConstants.HBASE_MASTER_LOADBALANCER_CLASS,
loadBalancerClazz,
LoadBalancer.class);
loadBalancer = LoadBalancerFactory.getLoadBalancer(conf);
+ MasterServices services = mock(MasterServices.class);
+ when(services.getConfiguration()).thenReturn(conf);
+ loadBalancer.setMasterServices(services);
+ try {
+ loadBalancer.initialize();
+ } catch (IOException e) {
+ LOG.error("Failed to initialize load balancer", e);
+ throw new RuntimeException("Failed to initialize load balancer", e);
+ }
}
private void generateRegionsAndServers() {
@@ -154,19 +167,19 @@ public class LoadBalancerPerformanceEvaluation extends
AbstractHBaseTool {
generateRegionsAndServers();
String methodName = "roundRobinAssignment";
- LOG.info("Calling " + methodName);
+ LOG.info("Calling {}", methodName);
Stopwatch watch = Stopwatch.createStarted();
loadBalancer.roundRobinAssignment(regions, servers);
System.out.print(formatResults(methodName,
watch.elapsed(TimeUnit.MILLISECONDS)));
methodName = "retainAssignment";
- LOG.info("Calling " + methodName);
+ LOG.info("Calling {}", methodName);
watch.reset().start();
loadBalancer.retainAssignment(regionServerMap, servers);
System.out.print(formatResults(methodName,
watch.elapsed(TimeUnit.MILLISECONDS)));
methodName = "balanceCluster";
- LOG.info("Calling " + methodName);
+ LOG.info("Calling {}", methodName);
watch.reset().start();
loadBalancer.balanceCluster(tableServerRegionMap);
diff --git
a/hbase-server/src/test/java/org/apache/hadoop/hbase/master/balancer/TestLoadBalancerPerformanceEvaluation.java
b/hbase-server/src/test/java/org/apache/hadoop/hbase/master/balancer/TestLoadBalancerPerformanceEvaluation.java
new file mode 100644
index 00000000000..b39907e9bf1
--- /dev/null
+++
b/hbase-server/src/test/java/org/apache/hadoop/hbase/master/balancer/TestLoadBalancerPerformanceEvaluation.java
@@ -0,0 +1,98 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.hadoop.hbase.master.balancer;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+import java.io.IOException;
+import org.apache.hadoop.hbase.HBaseConfiguration;
+import org.apache.hadoop.hbase.master.LoadBalancer;
+import org.apache.hadoop.hbase.testclassification.LargeTests;
+import org.apache.hadoop.hbase.testclassification.MasterTests;
+import org.apache.hadoop.hbase.util.AbstractHBaseTool;
+import org.apache.hadoop.metrics2.lib.DefaultMetricsSystem;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Tag;
+import org.junit.jupiter.api.Test;
+
+@Tag(MasterTests.TAG)
+@Tag(LargeTests.TAG)
+public class TestLoadBalancerPerformanceEvaluation {
+
+ private static final LoadBalancerPerformanceEvaluation tool =
+ new LoadBalancerPerformanceEvaluation();
+
+ @BeforeEach
+ public void setUpBeforeEach() {
+ tool.setConf(HBaseConfiguration.create());
+ }
+
+ @AfterEach
+ public void tearDownAfterEach() {
+ DefaultMetricsSystem.shutdown();
+ }
+
+ @Test
+ public void testLoadBalancerWithDefaultParams() throws IOException {
+ int ret = tool.run(new String[0]);
+ assertEquals(AbstractHBaseTool.EXIT_SUCCESS, ret);
+ }
+
+ @Test
+ public void testStochasticLoadBalancer() throws Exception {
+ testLoadBalancer(StochasticLoadBalancer.class);
+ }
+
+ @Test
+ public void testSimpleLoadBalancer() throws Exception {
+ testLoadBalancer(SimpleLoadBalancer.class);
+ }
+
+ private void testLoadBalancer(Class<? extends LoadBalancer>
loadBalancerClass) throws Exception {
+ String[] args =
+ { "-regions", "1000", "-servers", "100", "-load_balancer",
loadBalancerClass.getName() };
+ int ret = tool.run(args);
+ assertEquals(AbstractHBaseTool.EXIT_SUCCESS, ret);
+ }
+
+ @Test
+ public void testInvalidRegions() {
+ String[] args = { "-regions", "-100" };
+ IllegalArgumentException exception =
+ assertThrows(IllegalArgumentException.class, () -> tool.run(args));
+ assertEquals("Invalid number of regions!", exception.getMessage());
+ }
+
+ @Test
+ public void testInvalidServers() {
+ String[] args = { "-servers", "0" };
+ IllegalArgumentException exception =
+ assertThrows(IllegalArgumentException.class, () -> tool.run(args));
+ assertEquals("Invalid number of servers!", exception.getMessage());
+ }
+
+ @Test
+ public void testEmptyLoadBalancer() {
+ String[] args = { "-load_balancer", "" };
+ IllegalArgumentException exception =
+ assertThrows(IllegalArgumentException.class, () -> tool.run(args));
+ assertEquals("Invalid load balancer type!", exception.getMessage());
+ }
+}