HDFS-9229. Expose size of NameNode directory as a metric. Contributed by Surendra Singh Lilhore.

Change-Id: I985627a5d1400249d72d084283ef366d5ac6e07b
This commit is contained in:
Zhe Zhang 2015-10-29 11:14:00 -07:00
parent cf953b6258
commit 8def51a708
9 changed files with 122 additions and 2 deletions

View File

@ -240,6 +240,7 @@ Each metrics record contains tags such as HAState and Hostname as additional inf
| `LockQueueLength` | Number of threads waiting to acquire FSNameSystem lock | | `LockQueueLength` | Number of threads waiting to acquire FSNameSystem lock |
| `TotalSyncCount` | Total number of sync operations performed by edit log | | `TotalSyncCount` | Total number of sync operations performed by edit log |
| `TotalSyncTimes` | Total number of milliseconds spent by various edit logs in sync operation| | `TotalSyncTimes` | Total number of milliseconds spent by various edit logs in sync operation|
| `NameDirSize` | NameNode name directories size in bytes |
JournalNode JournalNode
----------- -----------

View File

@ -1608,6 +1608,9 @@ Release 2.8.0 - UNRELEASED
HDFS-8545. Refactor FS#getUsed() to use ContentSummary and add an API to fetch HDFS-8545. Refactor FS#getUsed() to use ContentSummary and add an API to fetch
the total file length from a specific path (J.Andreina via vinayakumarb) the total file length from a specific path (J.Andreina via vinayakumarb)
HDFS-9229. Expose size of NameNode directory as a metric.
(Surendra Singh Lilhore via zhz)
OPTIMIZATIONS OPTIMIZATIONS
HDFS-8026. Trace FSOutputSummer#writeChecksumChunks rather than HDFS-8026. Trace FSOutputSummer#writeChecksumChunks rather than

View File

@ -30,6 +30,7 @@
import java.util.List; import java.util.List;
import java.util.Properties; import java.util.Properties;
import org.apache.commons.io.FileUtils;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.apache.hadoop.classification.InterfaceAudience; import org.apache.hadoop.classification.InterfaceAudience;
@ -310,6 +311,20 @@ public StorageDirType getStorageDirType() {
return dirType; return dirType;
} }
/**
* Get storage directory size.
*/
public long getDirecorySize() {
try {
if (!isShared() && root != null && root.exists()) {
return FileUtils.sizeOfDirectory(root);
}
} catch (Exception e) {
LOG.warn("Failed to get directory size :" + root, e);
}
return 0;
}
public void read(File from, Storage storage) throws IOException { public void read(File from, Storage storage) throws IOException {
Properties props = readPropertiesFile(from); Properties props = readPropertiesFile(from);
storage.setFieldsFromProperties(props, this); storage.setFieldsFromProperties(props, this);

View File

@ -1064,6 +1064,8 @@ public synchronized void saveNamespace(FSNamesystem source, NameNodeFile nnf,
} finally { } finally {
removeFromCheckpointing(imageTxId); removeFromCheckpointing(imageTxId);
} }
//Update NameDirSize Metric
getStorage().updateNameDirSize();
} }
/** /**
@ -1244,6 +1246,8 @@ CheckpointSignature rollEditLog(int layoutVersion) throws IOException {
// we won't miss this log segment on a restart if the edits directories // we won't miss this log segment on a restart if the edits directories
// go missing. // go missing.
storage.writeTransactionIdFileToStorage(getEditLog().getCurSegmentTxId()); storage.writeTransactionIdFileToStorage(getEditLog().getCurSegmentTxId());
//Update NameDirSize Metric
getStorage().updateNameDirSize();
return new CheckpointSignature(this); return new CheckpointSignature(this);
} }

View File

@ -6402,6 +6402,11 @@ public String getSoftwareVersion() {
return VersionInfo.getVersion(); return VersionInfo.getVersion();
} }
@Override // NameNodeStatusMXBean
public String getNameDirSize() {
return getFSImage().getStorage().getNNDirectorySize();
}
/** /**
* Verifies that the given identifier and password are valid and match. * Verifies that the given identifier and password are valid and match.
* @param identifier Token identifier. * @param identifier Token identifier.

View File

@ -29,6 +29,7 @@
import java.util.HashMap; import java.util.HashMap;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Properties; import java.util.Properties;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.CopyOnWriteArrayList;
@ -52,6 +53,7 @@
import org.apache.hadoop.io.IOUtils; import org.apache.hadoop.io.IOUtils;
import org.apache.hadoop.net.DNS; import org.apache.hadoop.net.DNS;
import org.apache.hadoop.util.Time; import org.apache.hadoop.util.Time;
import org.mortbay.util.ajax.JSON;
import com.google.common.annotations.VisibleForTesting; import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Preconditions; import com.google.common.base.Preconditions;
@ -148,6 +150,11 @@ public boolean isOfType(StorageDirType type) {
*/ */
private HashMap<String, String> deprecatedProperties; private HashMap<String, String> deprecatedProperties;
/**
* Name directories size for metric.
*/
private Map<String, Long> nameDirSizeMap = new HashMap<>();
/** /**
* Construct the NNStorage. * Construct the NNStorage.
* @param conf Namenode configuration. * @param conf Namenode configuration.
@ -166,6 +173,8 @@ public NNStorage(Configuration conf,
setStorageDirectories(imageDirs, setStorageDirectories(imageDirs,
Lists.newArrayList(editsDirs), Lists.newArrayList(editsDirs),
FSNamesystem.getSharedEditsDirs(conf)); FSNamesystem.getSharedEditsDirs(conf));
//Update NameDirSize metric value after NN start
updateNameDirSize();
} }
@Override // Storage @Override // Storage
@ -1075,4 +1084,20 @@ public NamespaceInfo getNamespaceInfo() {
getBlockPoolID(), getBlockPoolID(),
getCTime()); getCTime());
} }
public String getNNDirectorySize() {
return JSON.toString(nameDirSizeMap);
}
public void updateNameDirSize() {
Map<String, Long> nnDirSizeMap = new HashMap<>();
for (Iterator<StorageDirectory> it = dirIterator(); it.hasNext();) {
StorageDirectory sd = it.next();
if (!sd.isShared()) {
nnDirSizeMap.put(sd.getRoot().getAbsolutePath(), sd.getDirecorySize());
}
}
nameDirSizeMap.clear();
nameDirSizeMap.putAll(nnDirSizeMap);
}
} }

View File

@ -272,4 +272,9 @@ public interface NameNodeMXBean {
*/ */
public Map<String, Integer> getDistinctVersions(); public Map<String, Integer> getDistinctVersions();
/**
* Get namenode directory size.
*/
String getNameDirSize();
} }

View File

@ -372,6 +372,8 @@ private void doWork() {
} finally { } finally {
namesystem.cpUnlock(); namesystem.cpUnlock();
} }
//Update NameDirSize Metric
namesystem.getFSImage().getStorage().updateNameDirSize();
} catch (EditLogInputException elie) { } catch (EditLogInputException elie) {
LOG.warn("Error while reading edits from disk. Will try again.", elie); LOG.warn("Error while reading edits from disk. Will try again.", elie);
} catch (InterruptedException ie) { } catch (InterruptedException ie) {
@ -463,4 +465,4 @@ private NamenodeProtocol getActiveNodeProxy() throws IOException {
return cachedActiveProxy; return cachedActiveProxy;
} }
} }
} }

View File

@ -26,12 +26,16 @@
import org.apache.hadoop.hdfs.DFSConfigKeys; import org.apache.hadoop.hdfs.DFSConfigKeys;
import org.apache.hadoop.hdfs.DFSTestUtil; import org.apache.hadoop.hdfs.DFSTestUtil;
import org.apache.hadoop.hdfs.MiniDFSCluster; import org.apache.hadoop.hdfs.MiniDFSCluster;
import org.apache.hadoop.hdfs.MiniDFSNNTopology;
import org.apache.hadoop.hdfs.protocol.HdfsConstants.SafeModeAction;
import org.apache.hadoop.hdfs.server.blockmanagement.DatanodeDescriptor; import org.apache.hadoop.hdfs.server.blockmanagement.DatanodeDescriptor;
import org.apache.hadoop.hdfs.server.blockmanagement.DatanodeManager; import org.apache.hadoop.hdfs.server.blockmanagement.DatanodeManager;
import org.apache.hadoop.hdfs.server.datanode.DataNode; import org.apache.hadoop.hdfs.server.datanode.DataNode;
import org.apache.hadoop.hdfs.server.namenode.ha.HATestUtil;
import org.apache.hadoop.hdfs.server.namenode.top.TopConf; import org.apache.hadoop.hdfs.server.namenode.top.TopConf;
import org.apache.hadoop.io.nativeio.NativeIO; import org.apache.hadoop.io.nativeio.NativeIO;
import org.apache.hadoop.io.nativeio.NativeIO.POSIX.NoMlockCacheManipulator; import org.apache.hadoop.io.nativeio.NativeIO.POSIX.NoMlockCacheManipulator;
import org.apache.hadoop.net.ServerSocketUtil;
import org.apache.hadoop.util.VersionInfo; import org.apache.hadoop.util.VersionInfo;
import org.codehaus.jackson.map.ObjectMapper; import org.codehaus.jackson.map.ObjectMapper;
import org.junit.Test; import org.junit.Test;
@ -40,6 +44,7 @@
import javax.management.MBeanServer; import javax.management.MBeanServer;
import javax.management.ObjectName; import javax.management.ObjectName;
import java.io.File; import java.io.File;
import java.io.IOException;
import java.lang.management.ManagementFactory; import java.lang.management.ManagementFactory;
import java.net.URI; import java.net.URI;
import java.util.Collection; import java.util.Collection;
@ -186,7 +191,7 @@ public void testNameNodeMXBeanInfo() throws Exception {
} }
assertEquals(2, statusMap.get("active").size()); assertEquals(2, statusMap.get("active").size());
assertEquals(0, statusMap.get("failed").size()); assertEquals(0, statusMap.get("failed").size());
// This will cause the first dir to fail. // This will cause the first dir to fail.
File failedNameDir = new File(nameDirUris.iterator().next()); File failedNameDir = new File(nameDirUris.iterator().next());
assertEquals(0, FileUtil.chmod( assertEquals(0, FileUtil.chmod(
@ -412,4 +417,59 @@ public void testQueueLength() throws Exception {
} }
} }
} }
@Test(timeout = 120000)
public void testNNDirectorySize() throws Exception{
Configuration conf = new Configuration();
conf.setInt(DFSConfigKeys.DFS_HA_TAILEDITS_PERIOD_KEY, 1);
// Have to specify IPC ports so the NNs can talk to each other.
MiniDFSNNTopology topology = new MiniDFSNNTopology()
.addNameservice(new MiniDFSNNTopology.NSConf("ns1")
.addNN(new MiniDFSNNTopology.NNConf("nn1")
.setIpcPort(ServerSocketUtil.getPort(0, 100)))
.addNN(new MiniDFSNNTopology.NNConf("nn2")
.setIpcPort(ServerSocketUtil.getPort(0, 100))));
MiniDFSCluster cluster = new MiniDFSCluster.Builder(conf)
.nnTopology(topology).numDataNodes(0)
.build();
FileSystem fs = null;
try {
cluster.waitActive();
FSNamesystem nn0 = cluster.getNamesystem(0);
FSNamesystem nn1 = cluster.getNamesystem(1);
checkNNDirSize(cluster.getNameDirs(0), nn0.getNameDirSize());
checkNNDirSize(cluster.getNameDirs(1), nn1.getNameDirSize());
cluster.transitionToActive(0);
fs = cluster.getFileSystem(0);
DFSTestUtil.createFile(fs, new Path("/file"), 0, (short) 1, 0L);
//rollEditLog
HATestUtil.waitForStandbyToCatchUp(cluster.getNameNode(0),
cluster.getNameNode(1));
checkNNDirSize(cluster.getNameDirs(0), nn0.getNameDirSize());
checkNNDirSize(cluster.getNameDirs(1), nn1.getNameDirSize());
//Test metric after call saveNamespace
DFSTestUtil.createFile(fs, new Path("/file"), 0, (short) 1, 0L);
nn0.setSafeMode(SafeModeAction.SAFEMODE_ENTER);
nn0.saveNamespace(0, 0);
checkNNDirSize(cluster.getNameDirs(0), nn0.getNameDirSize());
} finally {
cluster.shutdown();
}
}
@SuppressWarnings("unchecked")
private void checkNNDirSize(Collection<URI> nameDirUris, String metric){
Map<String, Long> nnDirMap =
(Map<String, Long>) JSON.parse(metric);
assertEquals(nameDirUris.size(), nnDirMap.size());
for (URI dirUrl : nameDirUris) {
File dir = new File(dirUrl);
assertEquals(nnDirMap.get(dir.getAbsolutePath()).longValue(),
FileUtils.sizeOfDirectory(dir));
}
}
} }