diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/balancer/CPRequestCostFunction.java b/hbase-balancer/src/main/java/org/apache/hadoop/hbase/master/balancer/CPRequestCostFunction.java similarity index 100% rename from hbase-server/src/main/java/org/apache/hadoop/hbase/master/balancer/CPRequestCostFunction.java rename to hbase-balancer/src/main/java/org/apache/hadoop/hbase/master/balancer/CPRequestCostFunction.java diff --git a/hbase-balancer/src/main/java/org/apache/hadoop/hbase/master/balancer/ClusterInfoProvider.java b/hbase-balancer/src/main/java/org/apache/hadoop/hbase/master/balancer/ClusterInfoProvider.java index 908bf9c36b6f..0721b7a58aed 100644 --- a/hbase-balancer/src/main/java/org/apache/hadoop/hbase/master/balancer/ClusterInfoProvider.java +++ b/hbase-balancer/src/main/java/org/apache/hadoop/hbase/master/balancer/ClusterInfoProvider.java @@ -22,13 +22,17 @@ import java.util.List; import java.util.Map; import java.util.function.Predicate; +import java.util.function.Supplier; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.hbase.HDFSBlocksDistribution; import org.apache.hadoop.hbase.ServerMetrics; import org.apache.hadoop.hbase.ServerName; import org.apache.hadoop.hbase.TableName; +import org.apache.hadoop.hbase.client.BalancerDecision; +import org.apache.hadoop.hbase.client.BalancerRejection; import org.apache.hadoop.hbase.client.RegionInfo; import org.apache.hadoop.hbase.client.TableDescriptor; +import org.apache.hadoop.hbase.conf.ConfigurationObserver; import org.apache.yetus.audience.InterfaceAudience; /** @@ -36,7 +40,7 @@ * want. */ @InterfaceAudience.Private -public interface ClusterInfoProvider { +public interface ClusterInfoProvider extends ConfigurationObserver { /** * Get the configuration. @@ -83,4 +87,21 @@ List getOnlineServersListWithPredicator(List servers, * Get a snapshot of the current assignment status. */ Map> getSnapShotOfAssignment(Collection regions); + + /** + * Test whether we are in off peak hour. + *

+ * For peak and off peak hours we may have different cost for the same balancing operation. + */ + boolean isOffPeakHour(); + + /** + * Record the given balancer decision. + */ + void recordBalancerDecision(Supplier decision); + + /** + * Record the given balancer rejection. + */ + void recordBalancerRejection(Supplier rejection); } diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/balancer/CostFromRegionLoadAsRateFunction.java b/hbase-balancer/src/main/java/org/apache/hadoop/hbase/master/balancer/CostFromRegionLoadAsRateFunction.java similarity index 100% rename from hbase-server/src/main/java/org/apache/hadoop/hbase/master/balancer/CostFromRegionLoadAsRateFunction.java rename to hbase-balancer/src/main/java/org/apache/hadoop/hbase/master/balancer/CostFromRegionLoadAsRateFunction.java diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/balancer/CostFromRegionLoadFunction.java b/hbase-balancer/src/main/java/org/apache/hadoop/hbase/master/balancer/CostFromRegionLoadFunction.java similarity index 100% rename from hbase-server/src/main/java/org/apache/hadoop/hbase/master/balancer/CostFromRegionLoadFunction.java rename to hbase-balancer/src/main/java/org/apache/hadoop/hbase/master/balancer/CostFromRegionLoadFunction.java diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/balancer/CostFunction.java b/hbase-balancer/src/main/java/org/apache/hadoop/hbase/master/balancer/CostFunction.java similarity index 100% rename from hbase-server/src/main/java/org/apache/hadoop/hbase/master/balancer/CostFunction.java rename to hbase-balancer/src/main/java/org/apache/hadoop/hbase/master/balancer/CostFunction.java diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/balancer/DoubleArrayCost.java b/hbase-balancer/src/main/java/org/apache/hadoop/hbase/master/balancer/DoubleArrayCost.java similarity index 100% rename from hbase-server/src/main/java/org/apache/hadoop/hbase/master/balancer/DoubleArrayCost.java rename to hbase-balancer/src/main/java/org/apache/hadoop/hbase/master/balancer/DoubleArrayCost.java diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/balancer/HeterogeneousRegionCountCostFunction.java b/hbase-balancer/src/main/java/org/apache/hadoop/hbase/master/balancer/HeterogeneousRegionCountCostFunction.java similarity index 92% rename from hbase-server/src/main/java/org/apache/hadoop/hbase/master/balancer/HeterogeneousRegionCountCostFunction.java rename to hbase-balancer/src/main/java/org/apache/hadoop/hbase/master/balancer/HeterogeneousRegionCountCostFunction.java index d2b4a5593d1d..4cda751e3b92 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/balancer/HeterogeneousRegionCountCostFunction.java +++ b/hbase-balancer/src/main/java/org/apache/hadoop/hbase/master/balancer/HeterogeneousRegionCountCostFunction.java @@ -16,16 +16,16 @@ import com.google.errorprone.annotations.RestrictedApi; import java.io.BufferedReader; -import java.io.FileReader; import java.io.IOException; import java.io.InputStreamReader; -import java.util.ArrayList; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Paths; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.regex.Pattern; import java.util.regex.PatternSyntaxException; - import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.fs.FileSystem; import org.apache.hadoop.fs.Path; @@ -34,6 +34,9 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.apache.hbase.thirdparty.com.google.common.base.Splitter; +import org.apache.hbase.thirdparty.com.google.common.io.CharStreams; + /** * This is an optional Cost function designed to allow region count skew across RegionServers. A * rule file is loaded from the local FS or HDFS before balancing. It contains lines of rules. A @@ -169,14 +172,14 @@ void loadRules() { if (line.startsWith("#")) { continue; } - final String[] splits = line.split(" "); - if (splits.length != 2) { + final List splits = Splitter.on(' ').splitToList(line); + if (splits.size() != 2) { throw new IOException( "line '" + line + "' is malformated, " + "expected [regexp] [limit]. Skipping line"); } - final Pattern pattern = Pattern.compile(splits[0]); - final Integer limit = Integer.parseInt(splits[1]); + final Pattern pattern = Pattern.compile(splits.get(0)); + final Integer limit = Integer.parseInt(splits.get(1)); this.limitPerRule.put(pattern, limit); } catch (final IOException | NumberFormatException | PatternSyntaxException e) { LOG.error("error on line: " + e); @@ -209,29 +212,17 @@ private List readFile(final String filename) { private List readFileFromHDFS(final String filename) throws IOException { final Path path = new Path(filename); final FileSystem fs = FileSystem.get(this.conf); - final BufferedReader reader = new BufferedReader(new InputStreamReader(fs.open(path))); - return readLines(reader); + try (BufferedReader reader = + new BufferedReader(new InputStreamReader(fs.open(path), StandardCharsets.UTF_8))) { + return CharStreams.readLines(reader); + } } /** * used to read the rule files from local FS */ private List readFileFromLocalFS(final String filename) throws IOException { - BufferedReader reader = new BufferedReader(new FileReader(filename)); - return readLines(reader); - } - - private List readLines(BufferedReader reader) throws IOException { - final List records = new ArrayList<>(); - try { - String line; - while ((line = reader.readLine()) != null) { - records.add(line); - } - } finally { - reader.close(); - } - return records; + return Files.readAllLines(Paths.get(filename), StandardCharsets.UTF_8); } /** diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/balancer/LocalityBasedCostFunction.java b/hbase-balancer/src/main/java/org/apache/hadoop/hbase/master/balancer/LocalityBasedCostFunction.java similarity index 100% rename from hbase-server/src/main/java/org/apache/hadoop/hbase/master/balancer/LocalityBasedCostFunction.java rename to hbase-balancer/src/main/java/org/apache/hadoop/hbase/master/balancer/LocalityBasedCostFunction.java diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/balancer/MemStoreSizeCostFunction.java b/hbase-balancer/src/main/java/org/apache/hadoop/hbase/master/balancer/MemStoreSizeCostFunction.java similarity index 100% rename from hbase-server/src/main/java/org/apache/hadoop/hbase/master/balancer/MemStoreSizeCostFunction.java rename to hbase-balancer/src/main/java/org/apache/hadoop/hbase/master/balancer/MemStoreSizeCostFunction.java diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/balancer/MoveCostFunction.java b/hbase-balancer/src/main/java/org/apache/hadoop/hbase/master/balancer/MoveCostFunction.java similarity index 93% rename from hbase-server/src/main/java/org/apache/hadoop/hbase/master/balancer/MoveCostFunction.java rename to hbase-balancer/src/main/java/org/apache/hadoop/hbase/master/balancer/MoveCostFunction.java index 9668461a6352..071f1350724e 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/balancer/MoveCostFunction.java +++ b/hbase-balancer/src/main/java/org/apache/hadoop/hbase/master/balancer/MoveCostFunction.java @@ -18,7 +18,6 @@ package org.apache.hadoop.hbase.master.balancer; import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.hbase.regionserver.compactions.OffPeakHours; import org.apache.yetus.audience.InterfaceAudience; /** @@ -38,14 +37,14 @@ class MoveCostFunction extends CostFunction { private static final float DEFAULT_MAX_MOVE_PERCENT = 0.25f; private final float maxMovesPercent; - private final OffPeakHours offPeakHours; + private final ClusterInfoProvider provider; private final float moveCost; private final float moveCostOffPeak; - MoveCostFunction(Configuration conf) { + MoveCostFunction(Configuration conf, ClusterInfoProvider provider) { + this.provider = provider; // What percent of the number of regions a single run of the balancer can move. maxMovesPercent = conf.getFloat(MAX_MOVES_PERCENT_KEY, DEFAULT_MAX_MOVE_PERCENT); - offPeakHours = OffPeakHours.getInstance(conf); moveCost = conf.getFloat(MOVE_COST_KEY, DEFAULT_MOVE_COST); moveCostOffPeak = conf.getFloat(MOVE_COST_OFFPEAK_KEY, DEFAULT_MOVE_COST_OFFPEAK); // Initialize the multiplier so that addCostFunction will add this cost function. @@ -58,7 +57,7 @@ void prepare(BalancerClusterState cluster) { super.prepare(cluster); // Move cost multiplier should be the same cost or higher than the rest of the costs to ensure // that large benefits are need to overcome the cost of a move. - if (offPeakHours.isOffPeakHour()) { + if (provider.isOffPeakHour()) { this.setMultiplier(moveCostOffPeak); } else { this.setMultiplier(moveCost); diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/balancer/PrimaryRegionCountSkewCostFunction.java b/hbase-balancer/src/main/java/org/apache/hadoop/hbase/master/balancer/PrimaryRegionCountSkewCostFunction.java similarity index 100% rename from hbase-server/src/main/java/org/apache/hadoop/hbase/master/balancer/PrimaryRegionCountSkewCostFunction.java rename to hbase-balancer/src/main/java/org/apache/hadoop/hbase/master/balancer/PrimaryRegionCountSkewCostFunction.java diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/balancer/RackLocalityCostFunction.java b/hbase-balancer/src/main/java/org/apache/hadoop/hbase/master/balancer/RackLocalityCostFunction.java similarity index 100% rename from hbase-server/src/main/java/org/apache/hadoop/hbase/master/balancer/RackLocalityCostFunction.java rename to hbase-balancer/src/main/java/org/apache/hadoop/hbase/master/balancer/RackLocalityCostFunction.java diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/balancer/ReadRequestCostFunction.java b/hbase-balancer/src/main/java/org/apache/hadoop/hbase/master/balancer/ReadRequestCostFunction.java similarity index 100% rename from hbase-server/src/main/java/org/apache/hadoop/hbase/master/balancer/ReadRequestCostFunction.java rename to hbase-balancer/src/main/java/org/apache/hadoop/hbase/master/balancer/ReadRequestCostFunction.java diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/balancer/RegionCountSkewCostFunction.java b/hbase-balancer/src/main/java/org/apache/hadoop/hbase/master/balancer/RegionCountSkewCostFunction.java similarity index 100% rename from hbase-server/src/main/java/org/apache/hadoop/hbase/master/balancer/RegionCountSkewCostFunction.java rename to hbase-balancer/src/main/java/org/apache/hadoop/hbase/master/balancer/RegionCountSkewCostFunction.java diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/balancer/RegionReplicaGroupingCostFunction.java b/hbase-balancer/src/main/java/org/apache/hadoop/hbase/master/balancer/RegionReplicaGroupingCostFunction.java similarity index 100% rename from hbase-server/src/main/java/org/apache/hadoop/hbase/master/balancer/RegionReplicaGroupingCostFunction.java rename to hbase-balancer/src/main/java/org/apache/hadoop/hbase/master/balancer/RegionReplicaGroupingCostFunction.java diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/balancer/RegionReplicaHostCostFunction.java b/hbase-balancer/src/main/java/org/apache/hadoop/hbase/master/balancer/RegionReplicaHostCostFunction.java similarity index 100% rename from hbase-server/src/main/java/org/apache/hadoop/hbase/master/balancer/RegionReplicaHostCostFunction.java rename to hbase-balancer/src/main/java/org/apache/hadoop/hbase/master/balancer/RegionReplicaHostCostFunction.java diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/balancer/RegionReplicaRackCostFunction.java b/hbase-balancer/src/main/java/org/apache/hadoop/hbase/master/balancer/RegionReplicaRackCostFunction.java similarity index 100% rename from hbase-server/src/main/java/org/apache/hadoop/hbase/master/balancer/RegionReplicaRackCostFunction.java rename to hbase-balancer/src/main/java/org/apache/hadoop/hbase/master/balancer/RegionReplicaRackCostFunction.java diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/balancer/ServerLocalityCostFunction.java b/hbase-balancer/src/main/java/org/apache/hadoop/hbase/master/balancer/ServerLocalityCostFunction.java similarity index 100% rename from hbase-server/src/main/java/org/apache/hadoop/hbase/master/balancer/ServerLocalityCostFunction.java rename to hbase-balancer/src/main/java/org/apache/hadoop/hbase/master/balancer/ServerLocalityCostFunction.java diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/balancer/StochasticLoadBalancer.java b/hbase-balancer/src/main/java/org/apache/hadoop/hbase/master/balancer/StochasticLoadBalancer.java similarity index 89% rename from hbase-server/src/main/java/org/apache/hadoop/hbase/master/balancer/StochasticLoadBalancer.java rename to hbase-balancer/src/main/java/org/apache/hadoop/hbase/master/balancer/StochasticLoadBalancer.java index 61b7f64ddd8b..a31361823769 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/balancer/StochasticLoadBalancer.java +++ b/hbase-balancer/src/main/java/org/apache/hadoop/hbase/master/balancer/StochasticLoadBalancer.java @@ -27,6 +27,7 @@ import java.util.List; import java.util.Map; import java.util.concurrent.ThreadLocalRandom; +import java.util.function.Supplier; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.hbase.ClusterMetrics; import org.apache.hadoop.hbase.HBaseInterfaceAudience; @@ -39,9 +40,6 @@ import org.apache.hadoop.hbase.client.RegionInfo; import org.apache.hadoop.hbase.master.RackManager; import org.apache.hadoop.hbase.master.RegionPlan; -import org.apache.hadoop.hbase.namequeues.BalancerDecisionDetails; -import org.apache.hadoop.hbase.namequeues.BalancerRejectionDetails; -import org.apache.hadoop.hbase.namequeues.NamedQueueRecorder; import org.apache.hadoop.hbase.util.EnvironmentEdgeManager; import org.apache.hadoop.hbase.util.ReflectionUtils; import org.apache.yetus.audience.InterfaceAudience; @@ -128,8 +126,6 @@ public class StochasticLoadBalancer extends BaseLoadBalancer { private long maxRunningTime = 30 * 1000 * 1; // 30 seconds. private int numRegionLoadsToRemember = 15; private float minCostNeedBalance = 0.05f; - private boolean isBalancerDecisionRecording = false; - private boolean isBalancerRejectionRecording = false; private List candidateGenerators; private List costFunctions; // FindBugs: Wants this protected; IS2_INCONSISTENT_SYNC @@ -147,11 +143,6 @@ public class StochasticLoadBalancer extends BaseLoadBalancer { private RegionReplicaHostCostFunction regionReplicaHostCostFunction; private RegionReplicaRackCostFunction regionReplicaRackCostFunction; - /** - * Use to add balancer decision history to ring-buffer - */ - NamedQueueRecorder namedQueueRecorder; - /** * The constructor that pass a MetricsStochasticBalancer to BaseLoadBalancer to replace its * default MetricsBalancer @@ -233,7 +224,7 @@ protected void loadConf(Configuration conf) { costFunctions = new ArrayList<>(); addCostFunction(new RegionCountSkewCostFunction(conf)); addCostFunction(new PrimaryRegionCountSkewCostFunction(conf)); - addCostFunction(new MoveCostFunction(conf)); + addCostFunction(new MoveCostFunction(conf, provider)); addCostFunction(localityCost); addCostFunction(rackLocalityCost); addCostFunction(new TableSkewCostFunction(conf)); @@ -249,17 +240,6 @@ protected void loadConf(Configuration conf) { curFunctionCosts = new double[costFunctions.size()]; tempFunctionCosts = new double[costFunctions.size()]; - isBalancerDecisionRecording = conf.getBoolean(BaseLoadBalancer.BALANCER_DECISION_BUFFER_ENABLED, - BaseLoadBalancer.DEFAULT_BALANCER_DECISION_BUFFER_ENABLED); - isBalancerRejectionRecording = - conf.getBoolean(BaseLoadBalancer.BALANCER_REJECTION_BUFFER_ENABLED, - BaseLoadBalancer.DEFAULT_BALANCER_REJECTION_BUFFER_ENABLED); - - if (this.namedQueueRecorder == null && - (isBalancerDecisionRecording || isBalancerRejectionRecording)) { - this.namedQueueRecorder = NamedQueueRecorder.getInstance(conf); - } - LOG.info("Loaded config; maxSteps=" + maxSteps + ", stepsPerRegion=" + stepsPerRegion + ", maxRunningTime=" + maxRunningTime + ", isByTable=" + isByTable + ", CostFunctions=" + Arrays.toString(getCostFunctionNames()) + " etc."); @@ -305,6 +285,19 @@ private boolean areSomeRegionReplicasColocated(BalancerClusterState c) { return false; } + private String getBalanceReason(double total, double sumMultiplier) { + if (total <= 0) { + return "(cost1*multiplier1)+(cost2*multiplier2)+...+(costn*multipliern) = " + total + " <= 0"; + } else if (sumMultiplier <= 0) { + return "sumMultiplier = " + sumMultiplier + " <= 0"; + } else if ((total / sumMultiplier) < minCostNeedBalance) { + return "[(cost1*multiplier1)+(cost2*multiplier2)+...+(costn*multipliern)]/sumMultiplier = " + + (total / sumMultiplier) + " <= minCostNeedBalance(" + minCostNeedBalance + ")"; + } else { + return ""; + } + } + @RestrictedApi(explanation = "Should only be called in tests", link = "", allowedOnPath = ".*(/src/test/.*|StochasticLoadBalancer).java") boolean needsBalance(TableName tableName, BalancerClusterState cluster) { @@ -314,10 +307,8 @@ boolean needsBalance(TableName tableName, BalancerClusterState cluster) { LOG.debug("Not running balancer because only " + cs.getNumServers() + " active regionserver(s)"); } - if (this.isBalancerRejectionRecording) { - sendRejectionReasonToRingBuffer("The number of RegionServers " + - cs.getNumServers() + " < MIN_SERVER_BALANCE(" + MIN_SERVER_BALANCE + ")", null); - } + sendRejectionReasonToRingBuffer(() -> "The number of RegionServers " + cs.getNumServers() + + " < MIN_SERVER_BALANCE(" + MIN_SERVER_BALANCE + ")", null); return false; } if (areSomeRegionReplicasColocated(cluster)) { @@ -346,18 +337,11 @@ boolean needsBalance(TableName tableName, BalancerClusterState cluster) { boolean balanced = total <= 0 || sumMultiplier <= 0 || (sumMultiplier > 0 && (total / sumMultiplier) < minCostNeedBalance); - if(balanced && isBalancerRejectionRecording){ - String reason = ""; - if (total <= 0) { - reason = "(cost1*multiplier1)+(cost2*multiplier2)+...+(costn*multipliern) = " + total + " <= 0"; - } else if (sumMultiplier <= 0) { - reason = "sumMultiplier = " + sumMultiplier + " <= 0"; - } else if ((total / sumMultiplier) < minCostNeedBalance) { - reason = - "[(cost1*multiplier1)+(cost2*multiplier2)+...+(costn*multipliern)]/sumMultiplier = " + (total - / sumMultiplier) + " <= minCostNeedBalance(" + minCostNeedBalance + ")"; - } - sendRejectionReasonToRingBuffer(reason, costFunctions); + if (balanced) { + final double calculatedTotal = total; + final double calculatedMultiplier = sumMultiplier; + sendRejectionReasonToRingBuffer(() -> getBalanceReason(calculatedTotal, calculatedMultiplier), + costFunctions); } if (LOG.isDebugEnabled()) { LOG.debug("{} {}; total cost={}, sum multiplier={}; cost/multiplier to need a balance is {}", @@ -500,11 +484,10 @@ protected List balanceTable(TableName tableName, Map costFunctions){ - if (this.isBalancerRejectionRecording){ - BalancerRejection.Builder builder = - new BalancerRejection.Builder() - .setReason(reason); + private void sendRejectionReasonToRingBuffer(Supplier reason, + List costFunctions) { + provider.recordBalancerRejection(() -> { + BalancerRejection.Builder builder = new BalancerRejection.Builder().setReason(reason.get()); if (costFunctions != null) { for (CostFunction c : costFunctions) { float multiplier = c.getMultiplier(); @@ -514,29 +497,24 @@ private void sendRejectionReasonToRingBuffer(String reason, List c builder.addCostFuncInfo(c.getClass().getName(), c.cost(), c.getMultiplier()); } } - namedQueueRecorder.addRecord(new BalancerRejectionDetails(builder.build())); - } + return builder.build(); + }); } private void sendRegionPlansToRingBuffer(List plans, double currentCost, - double initCost, String initFunctionTotalCosts, long step) { - if (this.isBalancerDecisionRecording) { + double initCost, String initFunctionTotalCosts, long step) { + provider.recordBalancerDecision(() -> { List regionPlans = new ArrayList<>(); for (RegionPlan plan : plans) { - regionPlans.add( - "table: " + plan.getRegionInfo().getTable() + " , region: " + plan.getRegionName() - + " , source: " + plan.getSource() + " , destination: " + plan.getDestination()); + regionPlans + .add("table: " + plan.getRegionInfo().getTable() + " , region: " + plan.getRegionName() + + " , source: " + plan.getSource() + " , destination: " + plan.getDestination()); } - BalancerDecision balancerDecision = - new BalancerDecision.Builder() - .setInitTotalCost(initCost) - .setInitialFunctionCosts(initFunctionTotalCosts) - .setComputedTotalCost(currentCost) - .setFinalFunctionCosts(totalCostsPerFunc()) - .setComputedSteps(step) - .setRegionPlans(regionPlans).build(); - namedQueueRecorder.addRecord(new BalancerDecisionDetails(balancerDecision)); - } + return new BalancerDecision.Builder().setInitTotalCost(initCost) + .setInitialFunctionCosts(initFunctionTotalCosts).setComputedTotalCost(currentCost) + .setFinalFunctionCosts(totalCostsPerFunc()).setComputedSteps(step) + .setRegionPlans(regionPlans).build(); + }); } /** diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/balancer/StoreFileCostFunction.java b/hbase-balancer/src/main/java/org/apache/hadoop/hbase/master/balancer/StoreFileCostFunction.java similarity index 100% rename from hbase-server/src/main/java/org/apache/hadoop/hbase/master/balancer/StoreFileCostFunction.java rename to hbase-balancer/src/main/java/org/apache/hadoop/hbase/master/balancer/StoreFileCostFunction.java diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/balancer/TableSkewCostFunction.java b/hbase-balancer/src/main/java/org/apache/hadoop/hbase/master/balancer/TableSkewCostFunction.java similarity index 100% rename from hbase-server/src/main/java/org/apache/hadoop/hbase/master/balancer/TableSkewCostFunction.java rename to hbase-balancer/src/main/java/org/apache/hadoop/hbase/master/balancer/TableSkewCostFunction.java diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/balancer/WriteRequestCostFunction.java b/hbase-balancer/src/main/java/org/apache/hadoop/hbase/master/balancer/WriteRequestCostFunction.java similarity index 100% rename from hbase-server/src/main/java/org/apache/hadoop/hbase/master/balancer/WriteRequestCostFunction.java rename to hbase-balancer/src/main/java/org/apache/hadoop/hbase/master/balancer/WriteRequestCostFunction.java diff --git a/hbase-balancer/src/test/java/org/apache/hadoop/hbase/master/balancer/DummyClusterInfoProvider.java b/hbase-balancer/src/test/java/org/apache/hadoop/hbase/master/balancer/DummyClusterInfoProvider.java index c56b1b8e39fe..3929e6d6716e 100644 --- a/hbase-balancer/src/test/java/org/apache/hadoop/hbase/master/balancer/DummyClusterInfoProvider.java +++ b/hbase-balancer/src/test/java/org/apache/hadoop/hbase/master/balancer/DummyClusterInfoProvider.java @@ -23,11 +23,14 @@ import java.util.List; import java.util.Map; import java.util.function.Predicate; +import java.util.function.Supplier; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.hbase.HDFSBlocksDistribution; import org.apache.hadoop.hbase.ServerMetrics; import org.apache.hadoop.hbase.ServerName; import org.apache.hadoop.hbase.TableName; +import org.apache.hadoop.hbase.client.BalancerDecision; +import org.apache.hadoop.hbase.client.BalancerRejection; import org.apache.hadoop.hbase.client.RegionInfo; import org.apache.hadoop.hbase.client.TableDescriptor; @@ -80,4 +83,21 @@ public List getOnlineServersListWithPredicator(List serv public Map> getSnapShotOfAssignment(Collection regions) { return Collections.emptyMap(); } + + @Override + public boolean isOffPeakHour() { + return false; + } + + @Override + public void recordBalancerDecision(Supplier decision) { + } + + @Override + public void recordBalancerRejection(Supplier rejection) { + } + + @Override + public void onConfigurationChange(Configuration conf) { + } } diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/master/balancer/DummyCostFunction.java b/hbase-balancer/src/test/java/org/apache/hadoop/hbase/master/balancer/DummyCostFunction.java similarity index 100% rename from hbase-server/src/test/java/org/apache/hadoop/hbase/master/balancer/DummyCostFunction.java rename to hbase-balancer/src/test/java/org/apache/hadoop/hbase/master/balancer/DummyCostFunction.java diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/master/balancer/StochasticBalancerTestBase.java b/hbase-balancer/src/test/java/org/apache/hadoop/hbase/master/balancer/StochasticBalancerTestBase.java similarity index 100% rename from hbase-server/src/test/java/org/apache/hadoop/hbase/master/balancer/StochasticBalancerTestBase.java rename to hbase-balancer/src/test/java/org/apache/hadoop/hbase/master/balancer/StochasticBalancerTestBase.java diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/master/balancer/StochasticBalancerTestBase2.java b/hbase-balancer/src/test/java/org/apache/hadoop/hbase/master/balancer/StochasticBalancerTestBase2.java similarity index 100% rename from hbase-server/src/test/java/org/apache/hadoop/hbase/master/balancer/StochasticBalancerTestBase2.java rename to hbase-balancer/src/test/java/org/apache/hadoop/hbase/master/balancer/StochasticBalancerTestBase2.java diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/master/balancer/TestStochasticLoadBalancer.java b/hbase-balancer/src/test/java/org/apache/hadoop/hbase/master/balancer/TestStochasticLoadBalancer.java similarity index 93% rename from hbase-server/src/test/java/org/apache/hadoop/hbase/master/balancer/TestStochasticLoadBalancer.java rename to hbase-balancer/src/test/java/org/apache/hadoop/hbase/master/balancer/TestStochasticLoadBalancer.java index e480b5b59bdb..c83e9dd2babc 100644 --- a/hbase-server/src/test/java/org/apache/hadoop/hbase/master/balancer/TestStochasticLoadBalancer.java +++ b/hbase-balancer/src/test/java/org/apache/hadoop/hbase/master/balancer/TestStochasticLoadBalancer.java @@ -32,7 +32,6 @@ import java.util.Map; import java.util.Queue; import java.util.Set; -import java.util.TimeZone; import java.util.TreeMap; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.hbase.ClusterMetrics; @@ -49,7 +48,6 @@ import org.apache.hadoop.hbase.testclassification.MasterTests; import org.apache.hadoop.hbase.testclassification.MediumTests; import org.apache.hadoop.hbase.util.Bytes; -import org.apache.hadoop.hbase.util.EnvironmentEdgeManager; import org.junit.ClassRule; import org.junit.Test; import org.junit.experimental.categories.Category; @@ -122,11 +120,11 @@ public class TestStochasticLoadBalancer extends StochasticBalancerTestBase { }, }; - private ServerMetrics mockServerMetricsWithCpRequests(ServerName server, - List regionsOnServer, long cpRequestCount) { + private ServerMetrics mockServerMetricsWithCpRequests(List regionsOnServer, + long cpRequestCount) { ServerMetrics serverMetrics = mock(ServerMetrics.class); Map regionLoadMap = new TreeMap<>(Bytes.BYTES_COMPARATOR); - for(RegionInfo info : regionsOnServer){ + for (RegionInfo info : regionsOnServer) { RegionMetrics rl = mock(RegionMetrics.class); when(rl.getReadRequestCount()).thenReturn(0L); when(rl.getCpRequestCount()).thenReturn(cpRequestCount); @@ -157,9 +155,9 @@ public void testCPRequestCost() { clusterState.put(serverC, regionsOnServerC); // mock ClusterMetrics Map serverMetricsMap = new TreeMap<>(); - serverMetricsMap.put(serverA, mockServerMetricsWithCpRequests(serverA, regionsOnServerA, 0)); - serverMetricsMap.put(serverB, mockServerMetricsWithCpRequests(serverB, regionsOnServerB, 0)); - serverMetricsMap.put(serverC, mockServerMetricsWithCpRequests(serverC, regionsOnServerC, 0)); + serverMetricsMap.put(serverA, mockServerMetricsWithCpRequests(regionsOnServerA, 0)); + serverMetricsMap.put(serverB, mockServerMetricsWithCpRequests(regionsOnServerB, 0)); + serverMetricsMap.put(serverC, mockServerMetricsWithCpRequests(regionsOnServerC, 0)); ClusterMetrics clusterStatus = mock(ClusterMetrics.class); when(clusterStatus.getLiveServerMetrics()).thenReturn(serverMetricsMap); loadBalancer.updateClusterMetrics(clusterStatus); @@ -171,9 +169,9 @@ public void testCPRequestCost() { // serverC : 0,0,0 // so should move two regions from serverA to serverB & serverC serverMetricsMap = new TreeMap<>(); - serverMetricsMap.put(serverA, mockServerMetricsWithCpRequests(serverA, regionsOnServerA, 1000)); - serverMetricsMap.put(serverB, mockServerMetricsWithCpRequests(serverB, regionsOnServerB, 0)); - serverMetricsMap.put(serverC, mockServerMetricsWithCpRequests(serverC, regionsOnServerC, 0)); + serverMetricsMap.put(serverA, mockServerMetricsWithCpRequests(regionsOnServerA, 1000)); + serverMetricsMap.put(serverB, mockServerMetricsWithCpRequests(regionsOnServerB, 0)); + serverMetricsMap.put(serverC, mockServerMetricsWithCpRequests(regionsOnServerC, 0)); clusterStatus = mock(ClusterMetrics.class); when(clusterStatus.getLiveServerMetrics()).thenReturn(serverMetricsMap); loadBalancer.updateClusterMetrics(clusterStatus); @@ -192,7 +190,6 @@ public void testCPRequestCost() { assertEquals(2, regionsMoveFromServerA.size()); assertEquals(2, targetServers.size()); assertTrue(regionsOnServerA.containsAll(regionsMoveFromServerA)); - assertNull(loadBalancer.namedQueueRecorder); // reset config conf.setFloat("hbase.master.balancer.stochastic.cpRequestCost", 5f); loadBalancer.onConfigurationChange(conf); @@ -220,7 +217,6 @@ public void testKeepRegionLoad() throws Exception { Map serverMetricsMap = new TreeMap<>(); serverMetricsMap.put(sn, sl); when(clusterStatus.getLiveServerMetrics()).thenReturn(serverMetricsMap); -// when(clusterStatus.getLoad(sn)).thenReturn(sl); loadBalancer.updateClusterMetrics(clusterStatus); } @@ -228,7 +224,6 @@ public void testKeepRegionLoad() throws Exception { String regionNameAsString = RegionInfo.getRegionNameAsString(Bytes.toBytes(REGION_KEY)); assertTrue(loadBalancer.loads.get(regionNameAsString) != null); assertTrue(loadBalancer.loads.get(regionNameAsString).size() == 15); - assertNull(loadBalancer.namedQueueRecorder); Queue loads = loadBalancer.loads.get(regionNameAsString); int i = 0; @@ -280,14 +275,15 @@ public void testLocalityCost() throws Exception { double expected = 1 - expectedLocalities[test]; assertEquals(expected, cost, 0.001); } - assertNull(loadBalancer.namedQueueRecorder); } @Test public void testMoveCostMultiplier() throws Exception { Configuration conf = HBaseConfiguration.create(); - CostFunction - costFunction = new MoveCostFunction(conf); + ClusterInfoProvider provider = mock(ClusterInfoProvider.class); + CostFunction costFunction = + new MoveCostFunction(conf, provider); + when(provider.isOffPeakHour()).thenReturn(false); BalancerClusterState cluster = mockCluster(clusterStateMocks[0]); costFunction.prepare(cluster); costFunction.cost(); @@ -295,25 +291,17 @@ public void testMoveCostMultiplier() throws Exception { costFunction.getMultiplier(), 0.01); // In offpeak hours, the multiplier of move cost should be lower - conf.setInt("hbase.offpeak.start.hour",0); - conf.setInt("hbase.offpeak.end.hour",23); - // Set a fixed time which hour is 15, so it will always in offpeak - // See HBASE-24898 for more info of the calculation here - long deltaFor15 = TimeZone.getDefault().getRawOffset() - 28800000; - long timeFor15 = 1597907081000L - deltaFor15; - EnvironmentEdgeManager.injectEdge(() -> timeFor15); - costFunction = new MoveCostFunction(conf); + when(provider.isOffPeakHour()).thenReturn(true); costFunction.prepare(cluster); costFunction.cost(); - assertEquals(MoveCostFunction.DEFAULT_MOVE_COST_OFFPEAK - , costFunction.getMultiplier(), 0.01); + assertEquals(MoveCostFunction.DEFAULT_MOVE_COST_OFFPEAK, + costFunction.getMultiplier(), 0.01); } @Test public void testMoveCost() throws Exception { Configuration conf = HBaseConfiguration.create(); - CostFunction - costFunction = new MoveCostFunction(conf); + CostFunction costFunction = new MoveCostFunction(conf, new DummyClusterInfoProvider(conf)); for (int[] mockCluster : clusterStateMocks) { BalancerClusterState cluster = mockCluster(mockCluster); costFunction.prepare(cluster); @@ -413,8 +401,8 @@ public void testRegionLoadCost() { List regionLoads = new ArrayList<>(); for (int i = 1; i < 5; i++) { BalancerRegionLoad regionLoad = mock(BalancerRegionLoad.class); - when(regionLoad.getReadRequestsCount()).thenReturn(new Long(i)); - when(regionLoad.getCpRequestsCount()).thenReturn(new Long(i)); + when(regionLoad.getReadRequestsCount()).thenReturn((long) i); + when(regionLoad.getCpRequestsCount()).thenReturn((long) i); when(regionLoad.getStorefileSizeMB()).thenReturn(i); regionLoads.add(regionLoad); } diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/master/balancer/TestStochasticLoadBalancerBalanceCluster.java b/hbase-balancer/src/test/java/org/apache/hadoop/hbase/master/balancer/TestStochasticLoadBalancerBalanceCluster.java similarity index 100% rename from hbase-server/src/test/java/org/apache/hadoop/hbase/master/balancer/TestStochasticLoadBalancerBalanceCluster.java rename to hbase-balancer/src/test/java/org/apache/hadoop/hbase/master/balancer/TestStochasticLoadBalancerBalanceCluster.java diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/master/balancer/TestStochasticLoadBalancerLargeCluster.java b/hbase-balancer/src/test/java/org/apache/hadoop/hbase/master/balancer/TestStochasticLoadBalancerLargeCluster.java similarity index 100% rename from hbase-server/src/test/java/org/apache/hadoop/hbase/master/balancer/TestStochasticLoadBalancerLargeCluster.java rename to hbase-balancer/src/test/java/org/apache/hadoop/hbase/master/balancer/TestStochasticLoadBalancerLargeCluster.java diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/master/balancer/TestStochasticLoadBalancerMidCluster.java b/hbase-balancer/src/test/java/org/apache/hadoop/hbase/master/balancer/TestStochasticLoadBalancerMidCluster.java similarity index 100% rename from hbase-server/src/test/java/org/apache/hadoop/hbase/master/balancer/TestStochasticLoadBalancerMidCluster.java rename to hbase-balancer/src/test/java/org/apache/hadoop/hbase/master/balancer/TestStochasticLoadBalancerMidCluster.java diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/master/balancer/TestStochasticLoadBalancerRegionReplica.java b/hbase-balancer/src/test/java/org/apache/hadoop/hbase/master/balancer/TestStochasticLoadBalancerRegionReplica.java similarity index 100% rename from hbase-server/src/test/java/org/apache/hadoop/hbase/master/balancer/TestStochasticLoadBalancerRegionReplica.java rename to hbase-balancer/src/test/java/org/apache/hadoop/hbase/master/balancer/TestStochasticLoadBalancerRegionReplica.java diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/master/balancer/TestStochasticLoadBalancerRegionReplicaHighReplication.java b/hbase-balancer/src/test/java/org/apache/hadoop/hbase/master/balancer/TestStochasticLoadBalancerRegionReplicaHighReplication.java similarity index 100% rename from hbase-server/src/test/java/org/apache/hadoop/hbase/master/balancer/TestStochasticLoadBalancerRegionReplicaHighReplication.java rename to hbase-balancer/src/test/java/org/apache/hadoop/hbase/master/balancer/TestStochasticLoadBalancerRegionReplicaHighReplication.java diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/master/balancer/TestStochasticLoadBalancerRegionReplicaLargeCluster.java b/hbase-balancer/src/test/java/org/apache/hadoop/hbase/master/balancer/TestStochasticLoadBalancerRegionReplicaLargeCluster.java similarity index 100% rename from hbase-server/src/test/java/org/apache/hadoop/hbase/master/balancer/TestStochasticLoadBalancerRegionReplicaLargeCluster.java rename to hbase-balancer/src/test/java/org/apache/hadoop/hbase/master/balancer/TestStochasticLoadBalancerRegionReplicaLargeCluster.java diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/master/balancer/TestStochasticLoadBalancerRegionReplicaMidCluster.java b/hbase-balancer/src/test/java/org/apache/hadoop/hbase/master/balancer/TestStochasticLoadBalancerRegionReplicaMidCluster.java similarity index 100% rename from hbase-server/src/test/java/org/apache/hadoop/hbase/master/balancer/TestStochasticLoadBalancerRegionReplicaMidCluster.java rename to hbase-balancer/src/test/java/org/apache/hadoop/hbase/master/balancer/TestStochasticLoadBalancerRegionReplicaMidCluster.java diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/master/balancer/TestStochasticLoadBalancerRegionReplicaReplicationGreaterThanNumNodes.java b/hbase-balancer/src/test/java/org/apache/hadoop/hbase/master/balancer/TestStochasticLoadBalancerRegionReplicaReplicationGreaterThanNumNodes.java similarity index 100% rename from hbase-server/src/test/java/org/apache/hadoop/hbase/master/balancer/TestStochasticLoadBalancerRegionReplicaReplicationGreaterThanNumNodes.java rename to hbase-balancer/src/test/java/org/apache/hadoop/hbase/master/balancer/TestStochasticLoadBalancerRegionReplicaReplicationGreaterThanNumNodes.java diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/master/balancer/TestStochasticLoadBalancerRegionReplicaSameHosts.java b/hbase-balancer/src/test/java/org/apache/hadoop/hbase/master/balancer/TestStochasticLoadBalancerRegionReplicaSameHosts.java similarity index 100% rename from hbase-server/src/test/java/org/apache/hadoop/hbase/master/balancer/TestStochasticLoadBalancerRegionReplicaSameHosts.java rename to hbase-balancer/src/test/java/org/apache/hadoop/hbase/master/balancer/TestStochasticLoadBalancerRegionReplicaSameHosts.java diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/master/balancer/TestStochasticLoadBalancerRegionReplicaWithRacks.java b/hbase-balancer/src/test/java/org/apache/hadoop/hbase/master/balancer/TestStochasticLoadBalancerRegionReplicaWithRacks.java similarity index 100% rename from hbase-server/src/test/java/org/apache/hadoop/hbase/master/balancer/TestStochasticLoadBalancerRegionReplicaWithRacks.java rename to hbase-balancer/src/test/java/org/apache/hadoop/hbase/master/balancer/TestStochasticLoadBalancerRegionReplicaWithRacks.java diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/master/balancer/TestStochasticLoadBalancerSmallCluster.java b/hbase-balancer/src/test/java/org/apache/hadoop/hbase/master/balancer/TestStochasticLoadBalancerSmallCluster.java similarity index 100% rename from hbase-server/src/test/java/org/apache/hadoop/hbase/master/balancer/TestStochasticLoadBalancerSmallCluster.java rename to hbase-balancer/src/test/java/org/apache/hadoop/hbase/master/balancer/TestStochasticLoadBalancerSmallCluster.java diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/balancer/MasterClusterInfoProvider.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/balancer/MasterClusterInfoProvider.java index afcfb34c8ba5..ea694cc47ba4 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/balancer/MasterClusterInfoProvider.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/balancer/MasterClusterInfoProvider.java @@ -17,24 +17,32 @@ */ package org.apache.hadoop.hbase.master.balancer; +import com.google.errorprone.annotations.RestrictedApi; import java.io.IOException; import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.function.Predicate; +import java.util.function.Supplier; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.hbase.HDFSBlocksDistribution; import org.apache.hadoop.hbase.ServerMetrics; import org.apache.hadoop.hbase.ServerName; import org.apache.hadoop.hbase.TableDescriptors; import org.apache.hadoop.hbase.TableName; +import org.apache.hadoop.hbase.client.BalancerDecision; +import org.apache.hadoop.hbase.client.BalancerRejection; import org.apache.hadoop.hbase.client.RegionInfo; import org.apache.hadoop.hbase.client.TableDescriptor; import org.apache.hadoop.hbase.master.MasterServices; import org.apache.hadoop.hbase.master.ServerManager; import org.apache.hadoop.hbase.master.assignment.AssignmentManager; +import org.apache.hadoop.hbase.namequeues.BalancerDecisionDetails; +import org.apache.hadoop.hbase.namequeues.BalancerRejectionDetails; +import org.apache.hadoop.hbase.namequeues.NamedQueueRecorder; import org.apache.hadoop.hbase.regionserver.HRegion; +import org.apache.hadoop.hbase.regionserver.compactions.OffPeakHours; import org.apache.yetus.audience.InterfaceAudience; /** @@ -45,8 +53,34 @@ public class MasterClusterInfoProvider implements ClusterInfoProvider { private final MasterServices services; + private boolean isBalancerDecisionRecording; + + private boolean isBalancerRejectionRecording; + + /** + * Use to add balancer decision history to ring-buffer + */ + private NamedQueueRecorder namedQueueRecorder; + + private OffPeakHours offPeakHours; + + private void loadConf(Configuration conf) { + this.offPeakHours = OffPeakHours.getInstance(conf); + isBalancerDecisionRecording = conf.getBoolean(BaseLoadBalancer.BALANCER_DECISION_BUFFER_ENABLED, + BaseLoadBalancer.DEFAULT_BALANCER_DECISION_BUFFER_ENABLED); + isBalancerRejectionRecording = + conf.getBoolean(BaseLoadBalancer.BALANCER_REJECTION_BUFFER_ENABLED, + BaseLoadBalancer.DEFAULT_BALANCER_REJECTION_BUFFER_ENABLED); + if (isBalancerDecisionRecording || isBalancerRejectionRecording) { + this.namedQueueRecorder = NamedQueueRecorder.getInstance(conf); + } else { + this.namedQueueRecorder = null; + } + } + public MasterClusterInfoProvider(MasterServices services) { this.services = services; + loadConf(services.getConfiguration()); } @Override @@ -106,4 +140,34 @@ public int getNumberOfTables() throws IOException { return services.getTableDescriptors().getAll().size(); } + @Override + public boolean isOffPeakHour() { + return offPeakHours.isOffPeakHour(); + } + + @Override + public void onConfigurationChange(Configuration conf) { + loadConf(conf); + } + + @Override + public void recordBalancerDecision(Supplier decision) { + if (isBalancerDecisionRecording) { + namedQueueRecorder.addRecord(new BalancerDecisionDetails(decision.get())); + } + } + + @Override + public void recordBalancerRejection(Supplier rejection) { + if (isBalancerRejectionRecording) { + namedQueueRecorder.addRecord(new BalancerRejectionDetails(rejection.get())); + } + } + + @RestrictedApi(explanation = "Should only be called in tests", link = "", + allowedOnPath = ".*/src/test/.*") + NamedQueueRecorder getNamedQueueRecorder() { + return namedQueueRecorder; + } + } diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/rsgroup/RSGroupBasedLoadBalancer.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/rsgroup/RSGroupBasedLoadBalancer.java index 183a4774e8b5..a4730c8d7361 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/rsgroup/RSGroupBasedLoadBalancer.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/rsgroup/RSGroupBasedLoadBalancer.java @@ -74,6 +74,7 @@ public class RSGroupBasedLoadBalancer implements LoadBalancer { private static final Logger LOG = LoggerFactory.getLogger(RSGroupBasedLoadBalancer.class); private MasterServices masterServices; + private ClusterInfoProvider provider; private FavoredNodesManager favoredNodesManager; private volatile RSGroupInfoManager rsGroupInfoManager; private volatile LoadBalancer internalBalancer; @@ -345,12 +346,13 @@ public void initialize() throws IOException { throw new IOException(e); } } + this.provider = new MasterClusterInfoProvider(masterServices); // avoid infinite nesting if (getClass().isAssignableFrom(balancerClass)) { balancerClass = LoadBalancerFactory.getDefaultLoadBalancerClass(); } internalBalancer = ReflectionUtils.newInstance(balancerClass); - internalBalancer.setClusterInfoProvider(new MasterClusterInfoProvider(masterServices)); + internalBalancer.setClusterInfoProvider(provider); // special handling for favor node balancers if (internalBalancer instanceof FavoredNodesPromoter) { favoredNodesManager = new FavoredNodesManager(masterServices); @@ -394,6 +396,7 @@ public synchronized void onConfigurationChange(Configuration conf) { fallbackEnabled, newFallbackEnabled); fallbackEnabled = newFallbackEnabled; } + provider.onConfigurationChange(conf); internalBalancer.onConfigurationChange(conf); } diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/master/balancer/TestBalancerDecision.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/master/balancer/TestBalancerDecision.java index 5395fc30287f..f7e1110283d1 100644 --- a/hbase-server/src/test/java/org/apache/hadoop/hbase/master/balancer/TestBalancerDecision.java +++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/master/balancer/TestBalancerDecision.java @@ -18,6 +18,9 @@ package org.apache.hadoop.hbase.master.balancer; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + import java.util.Arrays; import java.util.List; import java.util.Map; @@ -27,6 +30,7 @@ import org.apache.hadoop.hbase.TableName; import org.apache.hadoop.hbase.client.LogEntry; import org.apache.hadoop.hbase.client.RegionInfo; +import org.apache.hadoop.hbase.master.MasterServices; import org.apache.hadoop.hbase.master.RegionPlan; import org.apache.hadoop.hbase.namequeues.BalancerDecisionDetails; import org.apache.hadoop.hbase.namequeues.request.NamedQueueGetRequest; @@ -55,6 +59,10 @@ public class TestBalancerDecision extends StochasticBalancerTestBase { @Test public void testBalancerDecisions() { conf.setBoolean("hbase.master.balancer.decision.buffer.enabled", true); + MasterServices services = mock(MasterServices.class); + when(services.getConfiguration()).thenReturn(conf); + MasterClusterInfoProvider provider = new MasterClusterInfoProvider(services); + loadBalancer.setClusterInfoProvider(provider); loadBalancer.onConfigurationChange(conf); float minCost = conf.getFloat("hbase.master.balancer.stochastic.minCostNeedBalance", 0.05f); conf.setFloat("hbase.master.balancer.stochastic.minCostNeedBalance", 1.0f); @@ -78,7 +86,7 @@ public void testBalancerDecisions() { namedQueueGetRequest .setBalancerDecisionsRequest(MasterProtos.BalancerDecisionsRequest.getDefaultInstance()); NamedQueueGetResponse namedQueueGetResponse = - loadBalancer.namedQueueRecorder.getNamedQueueRecords(namedQueueGetRequest); + provider.getNamedQueueRecorder().getNamedQueueRecords(namedQueueGetRequest); List balancerDecisions = namedQueueGetResponse.getBalancerDecisions(); MasterProtos.BalancerDecisionsResponse response = diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/master/balancer/TestBalancerRejection.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/master/balancer/TestBalancerRejection.java index f3d991080cf3..98ab3eda6f5c 100644 --- a/hbase-server/src/test/java/org/apache/hadoop/hbase/master/balancer/TestBalancerRejection.java +++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/master/balancer/TestBalancerRejection.java @@ -18,6 +18,9 @@ package org.apache.hadoop.hbase.master.balancer; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + import java.util.List; import java.util.Map; import org.apache.hadoop.conf.Configuration; @@ -26,6 +29,7 @@ import org.apache.hadoop.hbase.TableName; import org.apache.hadoop.hbase.client.LogEntry; import org.apache.hadoop.hbase.client.RegionInfo; +import org.apache.hadoop.hbase.master.MasterServices; import org.apache.hadoop.hbase.namequeues.BalancerRejectionDetails; import org.apache.hadoop.hbase.namequeues.request.NamedQueueGetRequest; import org.apache.hadoop.hbase.namequeues.response.NamedQueueGetResponse; @@ -73,6 +77,10 @@ public void testBalancerRejections() throws Exception{ //enabled balancer rejection recording conf.setBoolean(BaseLoadBalancer.BALANCER_REJECTION_BUFFER_ENABLED, true); conf.set(StochasticLoadBalancer.COST_FUNCTIONS_COST_FUNCTIONS_KEY, MockCostFunction.class.getName()); + MasterServices services = mock(MasterServices.class); + when(services.getConfiguration()).thenReturn(conf); + MasterClusterInfoProvider provider = new MasterClusterInfoProvider(services); + loadBalancer.setClusterInfoProvider(provider); loadBalancer.onConfigurationChange(conf); //Simulate 2 servers with 5 regions. Map> servers = mockClusterServers(new int[] { 5, 5 }); @@ -91,11 +99,11 @@ public void testBalancerRejections() throws Exception{ //NamedQueue is an async Producer-consumer Pattern, waiting here until it completed int maxWaitingCount = 10; - while (maxWaitingCount-- > 0 && getBalancerRejectionLogEntries().size() != 2) { + while (maxWaitingCount-- > 0 && getBalancerRejectionLogEntries(provider).size() != 2) { Thread.sleep(1000); } //There are two cases, should be 2 logEntries - List logEntries = getBalancerRejectionLogEntries(); + List logEntries = getBalancerRejectionLogEntries(provider); Assert.assertEquals(2, logEntries.size()); Assert.assertTrue( logEntries.get(0).toJsonPrettyPrint().contains("minCostNeedBalance")); @@ -108,19 +116,18 @@ public void testBalancerRejections() throws Exception{ } } - private List getBalancerRejectionLogEntries(){ + private List getBalancerRejectionLogEntries(MasterClusterInfoProvider provider) { NamedQueueGetRequest namedQueueGetRequest = new NamedQueueGetRequest(); namedQueueGetRequest.setNamedQueueEvent(BalancerRejectionDetails.BALANCER_REJECTION_EVENT); - namedQueueGetRequest.setBalancerRejectionsRequest(MasterProtos.BalancerRejectionsRequest.getDefaultInstance()); + namedQueueGetRequest + .setBalancerRejectionsRequest(MasterProtos.BalancerRejectionsRequest.getDefaultInstance()); NamedQueueGetResponse namedQueueGetResponse = - loadBalancer.namedQueueRecorder.getNamedQueueRecords(namedQueueGetRequest); - List balancerRejections = namedQueueGetResponse.getBalancerRejections(); - MasterProtos.BalancerRejectionsResponse response = - MasterProtos.BalancerRejectionsResponse.newBuilder() - .addAllBalancerRejection(balancerRejections) - .build(); - List balancerRejectionRecords = - ProtobufUtil.getBalancerRejectionEntries(response); + provider.getNamedQueueRecorder().getNamedQueueRecords(namedQueueGetRequest); + List balancerRejections = + namedQueueGetResponse.getBalancerRejections(); + MasterProtos.BalancerRejectionsResponse response = MasterProtos.BalancerRejectionsResponse + .newBuilder().addAllBalancerRejection(balancerRejections).build(); + List balancerRejectionRecords = ProtobufUtil.getBalancerRejectionEntries(response); return balancerRejectionRecords; } } diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/master/balancer/TestRSGroupBasedLoadBalancerWithStochasticLoadBalancerAsInternal.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/master/balancer/TestRSGroupBasedLoadBalancerWithStochasticLoadBalancerAsInternal.java index 95e78477e195..7cde724f362a 100644 --- a/hbase-server/src/test/java/org/apache/hadoop/hbase/master/balancer/TestRSGroupBasedLoadBalancerWithStochasticLoadBalancerAsInternal.java +++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/master/balancer/TestRSGroupBasedLoadBalancerWithStochasticLoadBalancerAsInternal.java @@ -38,7 +38,6 @@ import org.apache.hadoop.hbase.TableName; import org.apache.hadoop.hbase.client.RegionInfo; import org.apache.hadoop.hbase.master.RegionPlan; -import org.apache.hadoop.hbase.master.balancer.BalancerTestBase.MockMapping; import org.apache.hadoop.hbase.rsgroup.RSGroupBasedLoadBalancer; import org.apache.hadoop.hbase.rsgroup.RSGroupInfo; import org.apache.hadoop.hbase.testclassification.LargeTests; diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/master/balancer/TestStochasticLoadBalancerHeterogeneousCost.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/master/balancer/TestStochasticLoadBalancerHeterogeneousCost.java index 0d418cd47217..66a46ca6317f 100644 --- a/hbase-server/src/test/java/org/apache/hadoop/hbase/master/balancer/TestStochasticLoadBalancerHeterogeneousCost.java +++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/master/balancer/TestStochasticLoadBalancerHeterogeneousCost.java @@ -17,6 +17,7 @@ import static junit.framework.TestCase.assertNotNull; import static junit.framework.TestCase.assertTrue; import static org.junit.Assert.assertNull; + import java.io.IOException; import java.util.Arrays; import java.util.Collections; @@ -27,7 +28,6 @@ import java.util.Random; import java.util.TreeMap; import java.util.concurrent.ThreadLocalRandom; - import org.apache.hadoop.fs.FileSystem; import org.apache.hadoop.hbase.HBaseClassTestRule; import org.apache.hadoop.hbase.HBaseTestingUtility;