HBASE-5325 Expose basic information about the master-status through jmx beans

git-svn-id: https://svn.apache.org/repos/asf/hbase/trunk@1293416 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Michael Stack 2012-02-24 21:06:12 +00:00
parent a54ec1b7cc
commit d7050d3541
9 changed files with 580 additions and 3 deletions

View File

@ -3163,6 +3163,10 @@ public class AssignmentManager extends ZooKeeperListener {
return region;
}
public ServerName getServerName() {
return serverName;
}
public boolean isClosing() {
return state == State.CLOSING;
}

View File

@ -37,6 +37,8 @@ import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import javax.management.ObjectName;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.hadoop.conf.Configuration;
@ -70,7 +72,6 @@ import org.apache.hadoop.hbase.ipc.HMasterInterface;
import org.apache.hadoop.hbase.ipc.HMasterRegionInterface;
import org.apache.hadoop.hbase.ipc.ProtocolSignature;
import org.apache.hadoop.hbase.ipc.RpcServer;
import org.apache.hadoop.hbase.master.CatalogJanitor.SplitParentFirstComparator;
import org.apache.hadoop.hbase.master.handler.CreateTableHandler;
import org.apache.hadoop.hbase.master.handler.DeleteTableHandler;
import org.apache.hadoop.hbase.master.handler.DisableTableHandler;
@ -103,6 +104,7 @@ import org.apache.hadoop.hbase.zookeeper.ZKUtil;
import org.apache.hadoop.hbase.zookeeper.ZooKeeperWatcher;
import org.apache.hadoop.io.MapWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.metrics.util.MBeanUtil;
import org.apache.hadoop.net.DNS;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.Watcher;
@ -125,7 +127,8 @@ import org.apache.zookeeper.Watcher;
* @see Watcher
*/
public class HMaster extends HasThread
implements HMasterInterface, HMasterRegionInterface, MasterServices, Server {
implements HMasterInterface, HMasterRegionInterface, MasterServices,
Server {
private static final Log LOG = LogFactory.getLog(HMaster.class.getName());
// MASTER is name of the webapp and the attribute name used stuffing this
@ -213,6 +216,11 @@ implements HMasterInterface, HMasterRegionInterface, MasterServices, Server {
private long masterStartTime;
private long masterActiveTime;
/**
* MX Bean for MasterInfo
*/
private ObjectName mxBean = null;
/**
* Initializes the HMaster. The steps are as follows:
* <p>
@ -547,6 +555,8 @@ implements HMasterInterface, HMasterRegionInterface, MasterServices, Server {
// Schema janitor chore.
this.schemaJanitorChore = getAndStartSchemaJanitorChore(this);
registerMBean();
status.markComplete("Initialization successful");
LOG.info("Master has completed initialization");
initialized = true;
@ -1377,6 +1387,7 @@ implements HMasterInterface, HMasterRegionInterface, MasterServices, Server {
this.assignmentManager.clearRegionFromTransition(hri);
}
}
/**
* @return cluster status
*/
@ -1434,7 +1445,7 @@ implements HMasterInterface, HMasterRegionInterface, MasterServices, Server {
public long getMasterActiveTime() {
return masterActiveTime;
}
/**
* @return array of coprocessor SimpleNames.
*/
@ -1577,6 +1588,7 @@ implements HMasterInterface, HMasterRegionInterface, MasterServices, Server {
return rsFatals;
}
@SuppressWarnings("deprecation")
@Override
public void shutdown() {
if (cpHost != null) {
@ -1586,6 +1598,10 @@ implements HMasterInterface, HMasterRegionInterface, MasterServices, Server {
LOG.error("Error call master coprocessor preShutdown()", ioe);
}
}
if (mxBean != null) {
MBeanUtil.unregisterMBean(mxBean);
mxBean = null;
}
if (this.assignmentManager != null) this.assignmentManager.shutdown();
if (this.serverManager != null) this.serverManager.shutdownCluster();
try {
@ -1788,4 +1804,14 @@ implements HMasterInterface, HMasterRegionInterface, MasterServices, Server {
VersionInfo.logVersion();
new HMasterCommandLine(HMaster.class).doMain(args);
}
/**
* Register bean with platform management server
*/
@SuppressWarnings("deprecation")
void registerMBean() {
MXBeanImpl mxBeanInfo = MXBeanImpl.init(this);
MBeanUtil.registerMBean("org.apache.hbase", "Master", mxBeanInfo);
LOG.info("Registered HMaster MXBean");
}
}

View File

@ -0,0 +1,118 @@
/**
* 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;
import java.util.Map;
import org.apache.hadoop.classification.InterfaceStability.Evolving;
import org.apache.hadoop.hbase.HServerLoad;
/**
* This is the JMX management interface for Hbase master information
*/
@Evolving
public interface MXBean {
/**
* Required for MXBean implementation
*/
public static interface RegionsInTransitionInfo {
/**
* Name of region in transition
*/
public String getRegionName();
/**
* Current transition state
*/
public String getRegionState();
/**
* Get Region Server name
*/
public String getRegionServerName();
/**
* Get last update time
*/
public long getLastUpdateTime();
}
/**
* Get ServerName
*/
public String getServerName();
/**
* Get Average Load
* @return Average Load
*/
public double getAverageLoad();
/**
* Get the Cluster ID
* @return Cluster ID
*/
public String getClusterId();
/**
* Get the Zookeeper Quorum Info
* @return Zookeeper Quorum Info
*/
public String getZookeeperQuorum();
/**
* Get the co-processors
* @return Co-processors
*/
public String[] getCoprocessors();
/**
* Get hbase master start time
* @return Start time of master in milliseconds
*/
public long getMasterStartTime();
/**
* Get the hbase master active time
* @return Time in milliseconds when master became active
*/
public long getMasterActiveTime();
/**
* Whether this master is the active master
* @return True if this is the active master
*/
public boolean getIsActiveMaster();
/**
* Get the live region servers
* @return Live region servers
*/
public Map<String, HServerLoad> getRegionServers();
/**
* Get the dead region servers
* @return Dead region Servers
*/
public String[] getDeadRegionServers();
/**
* Get information on regions in transition
* @return Regions in transition
*/
public RegionsInTransitionInfo[] getRegionsInTransition();
}

View File

@ -0,0 +1,150 @@
/**
* 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;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.apache.hadoop.hbase.HServerLoad;
import org.apache.hadoop.hbase.ServerName;
import org.apache.hadoop.hbase.master.AssignmentManager.RegionState;
/**
* Impl for exposing HMaster Information through JMX
*/
public class MXBeanImpl implements MXBean {
private final HMaster master;
private static MXBeanImpl instance = null;
public synchronized static MXBeanImpl init(final HMaster master) {
if (instance == null) {
instance = new MXBeanImpl(master);
}
return instance;
}
protected MXBeanImpl(final HMaster master) {
this.master = master;
}
@Override
public double getAverageLoad() {
return master.getAverageLoad();
}
@Override
public String getClusterId() {
return master.getClusterId();
}
@Override
public String getZookeeperQuorum() {
return master.getZooKeeperWatcher().getQuorum();
}
@Override
public String[] getCoprocessors() {
return master.getCoprocessors();
}
@Override
public long getMasterStartTime() {
return master.getMasterStartTime();
}
@Override
public long getMasterActiveTime() {
return master.getMasterActiveTime();
}
@Override
public Map<String, HServerLoad> getRegionServers() {
Map<String, HServerLoad> data = new HashMap<String, HServerLoad>();
for (final Entry<ServerName, HServerLoad> entry :
master.getServerManager().getOnlineServers().entrySet()) {
data.put(entry.getKey().getServerName(),
entry.getValue());
}
return data;
}
@Override
public String[] getDeadRegionServers() {
List<String> deadServers = new ArrayList<String>();
for (ServerName name : master.getServerManager().getDeadServers()) {
deadServers.add(name.getHostAndPort());
}
return deadServers.toArray(new String[0]);
}
@Override
public RegionsInTransitionInfo[] getRegionsInTransition() {
List<RegionsInTransitionInfo> info =
new ArrayList<RegionsInTransitionInfo>();
for (final Entry<String, RegionState> entry :
master.getAssignmentManager().getRegionsInTransition().entrySet()) {
RegionsInTransitionInfo innerinfo = new RegionsInTransitionInfo() {
@Override
public String getRegionState() {
return entry.getValue().getState().toString();
}
@Override
public String getRegionName() {
return entry.getKey();
}
@Override
public long getLastUpdateTime() {
return entry.getValue().getStamp();
}
@Override
public String getRegionServerName() {
ServerName serverName = entry.getValue().getServerName();
if (serverName != null) {
return serverName.getServerName();
}
else {
return "";
}
}
};
info.add(innerinfo);
}
RegionsInTransitionInfo[] data =
new RegionsInTransitionInfo[info.size()];
info.toArray(data);
return data;
}
@Override
public String getServerName() {
return master.getServerName().getServerName();
}
@Override
public boolean getIsActiveMaster() {
return master.isActiveMaster();
}
}

View File

@ -50,6 +50,8 @@ import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import javax.management.ObjectName;
import org.apache.commons.lang.mutable.MutableDouble;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@ -151,6 +153,7 @@ import org.apache.hadoop.hbase.zookeeper.ZooKeeperWatcher;
import org.apache.hadoop.io.MapWritable;
import org.apache.hadoop.io.Writable;
import org.apache.hadoop.ipc.RemoteException;
import org.apache.hadoop.metrics.util.MBeanUtil;
import org.apache.hadoop.net.DNS;
import org.apache.hadoop.util.ReflectionUtils;
import org.apache.hadoop.util.StringUtils;
@ -342,6 +345,11 @@ public class HRegionServer implements HRegionInterface, HBaseRPCErrorHandler,
private static final String OPEN = "OPEN";
private static final String CLOSE = "CLOSE";
/**
* MX Bean for RegionServerInfo
*/
private ObjectName mxBean = null;
/**
* Starts a HRegionServer at the default location
*
@ -648,6 +656,7 @@ public class HRegionServer implements HRegionInterface, HBaseRPCErrorHandler,
/**
* The HRegionServer sticks in this loop until closed.
*/
@SuppressWarnings("deprecation")
public void run() {
try {
// Do pre-registration initializations; zookeeper, lease threads, etc.
@ -669,6 +678,7 @@ public class HRegionServer implements HRegionInterface, HBaseRPCErrorHandler,
break;
}
}
registerMBean();
// We registered with the Master. Go into run mode.
long lastMsg = 0;
@ -715,6 +725,10 @@ public class HRegionServer implements HRegionInterface, HBaseRPCErrorHandler,
}
}
// Run shutdown.
if (mxBean != null) {
MBeanUtil.unregisterMBean(mxBean);
mxBean = null;
}
if (this.thriftServer != null) this.thriftServer.shutdown();
this.leases.closeAfterLeasesExpire();
this.rpcServer.stop();
@ -3680,4 +3694,16 @@ public class HRegionServer implements HRegionInterface, HBaseRPCErrorHandler,
HServerLoad hsl = buildServerLoad();
return hsl == null? null: hsl.getCoprocessors();
}
/**
* Register bean with platform management server
*/
@SuppressWarnings("deprecation")
void registerMBean() {
MXBeanImpl mxBeanInfo = MXBeanImpl.init(this);
mxBean = MBeanUtil.registerMBean("org.apache.hbase", "RegionServer",
mxBeanInfo);
LOG.info("Registered RegionServer MXBean");
}
}

View File

@ -0,0 +1,46 @@
/**
* 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.regionserver;
import org.apache.hadoop.classification.InterfaceStability.Evolving;
/**
* This is the JMX management interface for HBase Region Server information
*/
@Evolving
public interface MXBean {
/**
* Return RegionServer's ServerName
* @return ServerName
*/
public String getServerName();
/**
* Get loaded co-processors
* @return Loaded Co-processors
*/
public String[] getCoprocessors();
/**
* Get Zookeeper Quorum
* @return Comma-separated list of Zookeeper Quorum servers
*/
public String getZookeeperQuorum();
}

View File

@ -0,0 +1,54 @@
/**
* 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.regionserver;
/**
* Impl for exposing Region Server Information through JMX
*/
public class MXBeanImpl implements MXBean {
private final HRegionServer regionServer;
private static MXBeanImpl instance = null;
public synchronized static MXBeanImpl init(final HRegionServer rs){
if (instance == null) {
instance = new MXBeanImpl(rs);
}
return instance;
}
protected MXBeanImpl(final HRegionServer rs) {
this.regionServer = rs;
}
@Override
public String[] getCoprocessors() {
return regionServer.getCoprocessors();
}
@Override
public String getZookeeperQuorum() {
return regionServer.getZooKeeper().getQuorum();
}
@Override
public String getServerName() {
return regionServer.getServerName().getServerName();
}
}

View File

@ -0,0 +1,95 @@
/**
* 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;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import junit.framework.Assert;
import org.apache.hadoop.hbase.HBaseTestingUtility;
import org.apache.hadoop.hbase.HServerLoad;
import org.apache.hadoop.hbase.regionserver.HRegionServer;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
public class TestMXBean {
private static final HBaseTestingUtility TEST_UTIL =
new HBaseTestingUtility();
@BeforeClass
public static void setup() throws Exception {
TEST_UTIL.startMiniCluster(1, 4);
}
@AfterClass
public static void teardown() throws Exception {
TEST_UTIL.shutdownMiniCluster();
}
private void verifyRegionServers(Map<String, HServerLoad> regions) {
Set<String> expected = new HashSet<String>();
for (int i = 0; i < 4; ++i) {
HRegionServer rs = TEST_UTIL.getMiniHBaseCluster().getRegionServer(i);
expected.add(rs.getServerName().getServerName());
}
int found = 0;
for (java.util.Map.Entry<String, HServerLoad> entry : regions.entrySet()) {
if (expected.contains(entry.getKey())) {
++found;
}
}
Assert.assertEquals(4, found);
}
@Test
public void testInfo() {
HMaster master = TEST_UTIL.getHBaseCluster().getMaster();
MXBeanImpl info = MXBeanImpl.init(master);
Assert.assertEquals(master.getAverageLoad(), info.getAverageLoad());
Assert.assertEquals(master.getClusterId(), info.getClusterId());
Assert.assertEquals(master.getMasterActiveTime(),
info.getMasterActiveTime());
Assert.assertEquals(master.getMasterStartTime(),
info.getMasterStartTime());
Assert.assertEquals(master.getCoprocessors().length,
info.getCoprocessors().length);
Assert.assertEquals(master.getServerManager().getOnlineServersList().size(),
info.getRegionServers().size());
Assert.assertEquals(master.getAssignmentManager().isRegionsInTransition(),
info.getRegionsInTransition().length > 0);
Assert.assertTrue(info.getRegionServers().size() == 4);
String zkServers = info.getZookeeperQuorum();
Assert.assertEquals(zkServers.split(",").length,
TEST_UTIL.getZkCluster().getZooKeeperServerNum());
verifyRegionServers(info.getRegionServers());
TEST_UTIL.getMiniHBaseCluster().stopRegionServer(3, false);
TEST_UTIL.getMiniHBaseCluster().waitOnRegionServer(3);
Assert.assertTrue(info.getRegionServers().size() == 3);
Assert.assertTrue(info.getDeadRegionServers().length == 1);
}
}

View File

@ -0,0 +1,58 @@
/**
* 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.regionserver;
import junit.framework.Assert;
import org.apache.hadoop.hbase.HBaseTestingUtility;
import org.apache.hadoop.hbase.master.HMaster;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
public class TestMXBean {
private static final HBaseTestingUtility TEST_UTIL =
new HBaseTestingUtility();
@BeforeClass
public static void setup() throws Exception {
TEST_UTIL.startMiniCluster(1, 1);
}
@AfterClass
public static void teardown() throws Exception {
TEST_UTIL.shutdownMiniCluster();
}
@Test
public void testInfo() {
HRegionServer rs = TEST_UTIL.getMiniHBaseCluster().getRegionServer(0);
HMaster master = TEST_UTIL.getHBaseCluster().getMaster();
MXBeanImpl info = MXBeanImpl.init(rs);
Assert.assertEquals(rs.getServerName().getServerName(),
info.getServerName());
Assert.assertEquals(rs.getCoprocessors().length,
info.getCoprocessors().length);
rs.getConfiguration().setInt("hbase.master.info.port",
master.getServerName().getPort());
Assert.assertEquals(rs.getZooKeeperWatcher().getQuorum(),
info.getZookeeperQuorum());
}
}