HBASE-13222 Add isBalancerEnabled method to Master and Admin.

Include some basic tests for the method on a testing cluster.
Also update master page to show an alert when balancer is disabled.

Signed-off-by: Enis Soztutar <enis@apache.org>
This commit is contained in:
Josh Elser 2015-03-24 11:01:16 -04:00 committed by Enis Soztutar
parent a4a235b8d1
commit 98b1e72d1c
14 changed files with 1436 additions and 370 deletions

View File

@ -702,6 +702,13 @@ public interface Admin extends Abortable, Closeable {
*/
boolean balancer() throws IOException;
/**
* Query the current state of the balancer
*
* @return true if the balancer is enabled, false otherwise.
*/
boolean isBalancerEnabled() throws IOException;
/**
* Enable/Disable the catalog janitor
*

View File

@ -22,6 +22,7 @@ import com.google.common.annotations.VisibleForTesting;
import com.google.protobuf.BlockingRpcChannel;
import com.google.protobuf.RpcController;
import com.google.protobuf.ServiceException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.hadoop.conf.Configuration;
@ -53,6 +54,8 @@ import org.apache.hadoop.hbase.protobuf.RequestConverter;
import org.apache.hadoop.hbase.protobuf.generated.AdminProtos;
import org.apache.hadoop.hbase.protobuf.generated.ClientProtos;
import org.apache.hadoop.hbase.protobuf.generated.MasterProtos;
import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.IsBalancerEnabledRequest;
import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.IsBalancerEnabledResponse;
import org.apache.hadoop.hbase.regionserver.RegionServerStoppedException;
import org.apache.hadoop.hbase.security.User;
import org.apache.hadoop.hbase.util.Bytes;
@ -1589,6 +1592,12 @@ class ConnectionImplementation implements ClusterConnection, Closeable {
throws ServiceException {
return stub.getLastMajorCompactionTimestampForRegion(controller, request);
}
@Override
public IsBalancerEnabledResponse isBalancerEnabled(RpcController controller,
IsBalancerEnabledRequest request) throws ServiceException {
return stub.isBalancerEnabled(controller, request);
}
};
}

View File

@ -1970,6 +1970,23 @@ public class HBaseAdmin implements Admin {
});
}
/**
* Query the state of the balancer from the Master. It's not a guarantee that the balancer is
* actually running this very moment, but that it will run.
*
* @return True if the balancer is enabled, false otherwise.
*/
@Override
public boolean isBalancerEnabled() throws IOException {
return executeCallable(new MasterCallable<Boolean>(getConnection()) {
@Override
public Boolean call(int callTimeout) throws ServiceException {
return master.isBalancerEnabled(null, RequestConverter.buildIsBalancerEnabledRequest())
.getEnabled();
}
});
}
/**
* Enable/Disable the catalog janitor
* @param enable if true enables the catalog janitor

View File

@ -92,6 +92,7 @@ import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.GetSchemaAlterSta
import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.GetTableDescriptorsRequest;
import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.GetTableNamesRequest;
import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.GetTableStateRequest;
import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.IsBalancerEnabledRequest;
import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.IsCatalogJanitorEnabledRequest;
import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.IsMasterRunningRequest;
import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.ModifyColumnRequest;
@ -1339,6 +1340,15 @@ public final class RequestConverter {
return SetBalancerRunningRequest.newBuilder().setOn(on).setSynchronous(synchronous).build();
}
/**
* Creates a protocol buffer IsBalancerEnabledRequest
*
* @return a IsBalancerEnabledRequest
*/
public static IsBalancerEnabledRequest buildIsBalancerEnabledRequest() {
return IsBalancerEnabledRequest.newBuilder().build();
}
/**
* @see {@link #buildGetClusterStatusRequest}
*/

View File

@ -232,6 +232,13 @@ message SetBalancerRunningResponse {
optional bool prev_balance_value = 1;
}
message IsBalancerEnabledRequest {
}
message IsBalancerEnabledResponse {
required bool enabled = 1;
}
message RunCatalogScanRequest {
}
@ -508,6 +515,12 @@ service MasterService {
rpc SetBalancerRunning(SetBalancerRunningRequest)
returns(SetBalancerRunningResponse);
/**
* Query whether the Region Balancer is running.
*/
rpc IsBalancerEnabled(IsBalancerEnabledRequest)
returns(IsBalancerEnabledResponse);
/** Get a run of the catalog janitor */
rpc RunCatalogScan(RunCatalogScanRequest)
returns(RunCatalogScanResponse);

View File

@ -158,6 +158,13 @@ AssignmentManager assignmentManager = master.getAssignmentManager();
re-enabled from the hbase shell by running the command 'catalogjanitor_switch true'
</div>
</%if>
<%if !master.isBalancerOn() %>
<div class="alert alert-warning">
The Load Balancer is not enabled which will eventually cause performance degradation
in HBase as Regions will not be distributed across all RegionServers. The balancer
is only expected to be disabled during rolling upgrade scenarios.
</div>
</%if>
<section>
<h2>Region Servers</h2>
@ -298,6 +305,11 @@ AssignmentManager assignmentManager = master.getAssignmentManager();
java.util.Arrays.toString(master.getMasterCoprocessors()) %></td>
<td>Coprocessors currently loaded by the master</td>
</tr>
<tr>
<td>LoadBalancer</td>
<td><% master.getLoadBalancerClassName() %></td>
<td>LoadBalancer to be used in the Master</td>
</tr>
</%if>
</table>
</section>

View File

@ -2302,4 +2302,25 @@ public class HMaster extends HRegionServer implements MasterServices, Server {
public long getLastMajorCompactionTimestampForRegion(byte[] regionName) throws IOException {
return getClusterStatus().getLastMajorCompactionTsForRegion(regionName);
}
/**
* Queries the state of the {@link LoadBalancerTracker}. If the balancer is not initialized,
* false is returned.
*
* @return The state of the load balancer, or false if the load balancer isn't defined.
*/
public boolean isBalancerOn() {
if (null == loadBalancerTracker) return false;
return loadBalancerTracker.isBalancerOn();
}
/**
* Fetch the configured {@link LoadBalancer} class name. If none is set, a default is returned.
*
* @return The name of the {@link LoadBalancer} in use.
*/
public String getLoadBalancerClassName() {
return conf.get(HConstants.HBASE_MASTER_LOADBALANCER_CLASS, LoadBalancerFactory
.getDefaultLoadBalancerClass().getName());
}
}

View File

@ -92,6 +92,8 @@ import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.GetTableDescripto
import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.GetTableDescriptorsResponse;
import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.GetTableNamesRequest;
import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.GetTableNamesResponse;
import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.IsBalancerEnabledRequest;
import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.IsBalancerEnabledResponse;
import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.IsCatalogJanitorEnabledRequest;
import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.IsCatalogJanitorEnabledResponse;
import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.IsMasterRunningRequest;
@ -1305,4 +1307,12 @@ public class MasterRpcServices extends RSRpcServices
}
return response.build();
}
@Override
public IsBalancerEnabledResponse isBalancerEnabled(RpcController controller,
IsBalancerEnabledRequest request) throws ServiceException {
IsBalancerEnabledResponse.Builder response = IsBalancerEnabledResponse.newBuilder();
response.setEnabled(master.isBalancerOn());
return response.build();
}
}

View File

@ -29,6 +29,15 @@ import org.apache.hadoop.util.ReflectionUtils;
@InterfaceAudience.Private
public class LoadBalancerFactory {
/**
* The default {@link LoadBalancer} class.
*
* @return The Class for the default {@link LoadBalancer}.
*/
public static Class<? extends LoadBalancer> getDefaultLoadBalancerClass() {
return StochasticLoadBalancer.class;
}
/**
* Create a loadbalancer from the given conf.
* @param conf
@ -38,7 +47,7 @@ public class LoadBalancerFactory {
// Create the balancer
Class<? extends LoadBalancer> balancerKlass =
conf.getClass(HConstants.HBASE_MASTER_LOADBALANCER_CLASS, StochasticLoadBalancer.class,
conf.getClass(HConstants.HBASE_MASTER_LOADBALANCER_CLASS, getDefaultLoadBalancerClass(),
LoadBalancer.class);
return ReflectionUtils.newInstance(balancerKlass, conf);

View File

@ -726,4 +726,26 @@ public class TestAdmin2 {
pair = rawAdmin.getRegion(region.getEncodedNameAsBytes());
assertTrue(Bytes.equals(regionName, pair.getFirst().getRegionName()));
}
@Test(timeout = 30000)
public void testBalancer() throws Exception {
boolean initialState = admin.isBalancerEnabled();
// Start the balancer, wait for it.
boolean prevState = admin.setBalancerRunning(!initialState, true);
// The previous state should be the original state we observed
assertEquals(initialState, prevState);
// Current state should be opposite of the original
assertEquals(!initialState, admin.isBalancerEnabled());
// Reset it back to what it was
prevState = admin.setBalancerRunning(initialState, true);
// The previous state should be the opposite of the initial state
assertEquals(!initialState, prevState);
// Current state should be the original state again
assertEquals(initialState, admin.isBalancerEnabled());
}
}

View File

@ -114,6 +114,13 @@ module Hbase
java.lang.Boolean::valueOf(enableDisable), java.lang.Boolean::valueOf(false))
end
#----------------------------------------------------------------------------------------------
# Query the current state of the LoadBalancer.
# Returns the balancer's state (true is enabled).
def balancer_enabled?()
@admin.isBalancerEnabled()
end
#----------------------------------------------------------------------------------------------
# Request a scan of the catalog table (for garbage collection)
# Returns an int signifying the number of entries cleaned

View File

@ -313,6 +313,7 @@ Shell.load_command_group(
assign
balancer
balance_switch
balancer_enabled
close_region
compact
flush

View File

@ -0,0 +1,41 @@
#!/usr/bin/env hbase-jruby
#
# 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.
# Prints the current balancer status
module Shell
module Commands
class BalancerEnabled < Command
def help
return <<-EOF
Query the balancer's state.
Examples:
hbase> balancer_enabled
EOF
end
def command()
format_simple_command do
formatter.row([
admin.balancer_enabled?.to_s
])
end
end
end
end
end