|
@@ -140,6 +140,9 @@ public class DatanodeManager {
|
|
/** Whether or not to avoid using stale DataNodes for reading */
|
|
/** Whether or not to avoid using stale DataNodes for reading */
|
|
private final boolean avoidStaleDataNodesForRead;
|
|
private final boolean avoidStaleDataNodesForRead;
|
|
|
|
|
|
|
|
+ /** Whether or not to avoid using slow DataNodes for reading. */
|
|
|
|
+ private final boolean avoidSlowDataNodesForRead;
|
|
|
|
+
|
|
/** Whether or not to consider lad for reading. */
|
|
/** Whether or not to consider lad for reading. */
|
|
private final boolean readConsiderLoad;
|
|
private final boolean readConsiderLoad;
|
|
|
|
|
|
@@ -210,7 +213,7 @@ public class DatanodeManager {
|
|
|
|
|
|
@Nullable
|
|
@Nullable
|
|
private final SlowPeerTracker slowPeerTracker;
|
|
private final SlowPeerTracker slowPeerTracker;
|
|
- private static Set<Node> slowNodesSet = Sets.newConcurrentHashSet();
|
|
|
|
|
|
+ private static Set<String> slowNodesUuidSet = Sets.newConcurrentHashSet();
|
|
private Daemon slowPeerCollectorDaemon;
|
|
private Daemon slowPeerCollectorDaemon;
|
|
private final long slowPeerCollectionInterval;
|
|
private final long slowPeerCollectionInterval;
|
|
private final int maxSlowPeerReportNodes;
|
|
private final int maxSlowPeerReportNodes;
|
|
@@ -242,7 +245,6 @@ public class DatanodeManager {
|
|
} else {
|
|
} else {
|
|
networktopology = NetworkTopology.getInstance(conf);
|
|
networktopology = NetworkTopology.getInstance(conf);
|
|
}
|
|
}
|
|
-
|
|
|
|
this.heartbeatManager = new HeartbeatManager(namesystem,
|
|
this.heartbeatManager = new HeartbeatManager(namesystem,
|
|
blockManager, conf);
|
|
blockManager, conf);
|
|
this.datanodeAdminManager = new DatanodeAdminManager(namesystem,
|
|
this.datanodeAdminManager = new DatanodeAdminManager(namesystem,
|
|
@@ -273,7 +275,6 @@ public class DatanodeManager {
|
|
}
|
|
}
|
|
this.slowDiskTracker = dataNodeDiskStatsEnabled ?
|
|
this.slowDiskTracker = dataNodeDiskStatsEnabled ?
|
|
new SlowDiskTracker(conf, timer) : null;
|
|
new SlowDiskTracker(conf, timer) : null;
|
|
-
|
|
|
|
this.defaultXferPort = NetUtils.createSocketAddr(
|
|
this.defaultXferPort = NetUtils.createSocketAddr(
|
|
conf.getTrimmed(DFSConfigKeys.DFS_DATANODE_ADDRESS_KEY,
|
|
conf.getTrimmed(DFSConfigKeys.DFS_DATANODE_ADDRESS_KEY,
|
|
DFSConfigKeys.DFS_DATANODE_ADDRESS_DEFAULT)).getPort();
|
|
DFSConfigKeys.DFS_DATANODE_ADDRESS_DEFAULT)).getPort();
|
|
@@ -294,11 +295,9 @@ public class DatanodeManager {
|
|
} catch (IOException e) {
|
|
} catch (IOException e) {
|
|
LOG.error("error reading hosts files: ", e);
|
|
LOG.error("error reading hosts files: ", e);
|
|
}
|
|
}
|
|
-
|
|
|
|
this.dnsToSwitchMapping = ReflectionUtils.newInstance(
|
|
this.dnsToSwitchMapping = ReflectionUtils.newInstance(
|
|
conf.getClass(DFSConfigKeys.NET_TOPOLOGY_NODE_SWITCH_MAPPING_IMPL_KEY,
|
|
conf.getClass(DFSConfigKeys.NET_TOPOLOGY_NODE_SWITCH_MAPPING_IMPL_KEY,
|
|
ScriptBasedMapping.class, DNSToSwitchMapping.class), conf);
|
|
ScriptBasedMapping.class, DNSToSwitchMapping.class), conf);
|
|
-
|
|
|
|
this.rejectUnresolvedTopologyDN = conf.getBoolean(
|
|
this.rejectUnresolvedTopologyDN = conf.getBoolean(
|
|
DFSConfigKeys.DFS_REJECT_UNRESOLVED_DN_TOPOLOGY_MAPPING_KEY,
|
|
DFSConfigKeys.DFS_REJECT_UNRESOLVED_DN_TOPOLOGY_MAPPING_KEY,
|
|
DFSConfigKeys.DFS_REJECT_UNRESOLVED_DN_TOPOLOGY_MAPPING_DEFAULT);
|
|
DFSConfigKeys.DFS_REJECT_UNRESOLVED_DN_TOPOLOGY_MAPPING_DEFAULT);
|
|
@@ -313,7 +312,6 @@ public class DatanodeManager {
|
|
}
|
|
}
|
|
dnsToSwitchMapping.resolve(locations);
|
|
dnsToSwitchMapping.resolve(locations);
|
|
}
|
|
}
|
|
-
|
|
|
|
heartbeatIntervalSeconds = conf.getTimeDuration(
|
|
heartbeatIntervalSeconds = conf.getTimeDuration(
|
|
DFSConfigKeys.DFS_HEARTBEAT_INTERVAL_KEY,
|
|
DFSConfigKeys.DFS_HEARTBEAT_INTERVAL_KEY,
|
|
DFSConfigKeys.DFS_HEARTBEAT_INTERVAL_DEFAULT, TimeUnit.SECONDS);
|
|
DFSConfigKeys.DFS_HEARTBEAT_INTERVAL_DEFAULT, TimeUnit.SECONDS);
|
|
@@ -322,7 +320,6 @@ public class DatanodeManager {
|
|
DFSConfigKeys.DFS_NAMENODE_HEARTBEAT_RECHECK_INTERVAL_DEFAULT); // 5 minutes
|
|
DFSConfigKeys.DFS_NAMENODE_HEARTBEAT_RECHECK_INTERVAL_DEFAULT); // 5 minutes
|
|
this.heartbeatExpireInterval = 2 * heartbeatRecheckInterval
|
|
this.heartbeatExpireInterval = 2 * heartbeatRecheckInterval
|
|
+ 10 * 1000 * heartbeatIntervalSeconds;
|
|
+ 10 * 1000 * heartbeatIntervalSeconds;
|
|
-
|
|
|
|
// Effected block invalidate limit is the bigger value between
|
|
// Effected block invalidate limit is the bigger value between
|
|
// value configured in hdfs-site.xml, and 20 * HB interval.
|
|
// value configured in hdfs-site.xml, and 20 * HB interval.
|
|
final int configuredBlockInvalidateLimit = conf.getInt(
|
|
final int configuredBlockInvalidateLimit = conf.getInt(
|
|
@@ -335,16 +332,17 @@ public class DatanodeManager {
|
|
+ ": configured=" + configuredBlockInvalidateLimit
|
|
+ ": configured=" + configuredBlockInvalidateLimit
|
|
+ ", counted=" + countedBlockInvalidateLimit
|
|
+ ", counted=" + countedBlockInvalidateLimit
|
|
+ ", effected=" + blockInvalidateLimit);
|
|
+ ", effected=" + blockInvalidateLimit);
|
|
-
|
|
|
|
this.checkIpHostnameInRegistration = conf.getBoolean(
|
|
this.checkIpHostnameInRegistration = conf.getBoolean(
|
|
DFSConfigKeys.DFS_NAMENODE_DATANODE_REGISTRATION_IP_HOSTNAME_CHECK_KEY,
|
|
DFSConfigKeys.DFS_NAMENODE_DATANODE_REGISTRATION_IP_HOSTNAME_CHECK_KEY,
|
|
DFSConfigKeys.DFS_NAMENODE_DATANODE_REGISTRATION_IP_HOSTNAME_CHECK_DEFAULT);
|
|
DFSConfigKeys.DFS_NAMENODE_DATANODE_REGISTRATION_IP_HOSTNAME_CHECK_DEFAULT);
|
|
LOG.info(DFSConfigKeys.DFS_NAMENODE_DATANODE_REGISTRATION_IP_HOSTNAME_CHECK_KEY
|
|
LOG.info(DFSConfigKeys.DFS_NAMENODE_DATANODE_REGISTRATION_IP_HOSTNAME_CHECK_KEY
|
|
+ "=" + checkIpHostnameInRegistration);
|
|
+ "=" + checkIpHostnameInRegistration);
|
|
-
|
|
|
|
this.avoidStaleDataNodesForRead = conf.getBoolean(
|
|
this.avoidStaleDataNodesForRead = conf.getBoolean(
|
|
DFSConfigKeys.DFS_NAMENODE_AVOID_STALE_DATANODE_FOR_READ_KEY,
|
|
DFSConfigKeys.DFS_NAMENODE_AVOID_STALE_DATANODE_FOR_READ_KEY,
|
|
DFSConfigKeys.DFS_NAMENODE_AVOID_STALE_DATANODE_FOR_READ_DEFAULT);
|
|
DFSConfigKeys.DFS_NAMENODE_AVOID_STALE_DATANODE_FOR_READ_DEFAULT);
|
|
|
|
+ this.avoidSlowDataNodesForRead = conf.getBoolean(
|
|
|
|
+ DFSConfigKeys.DFS_NAMENODE_AVOID_SLOW_DATANODE_FOR_READ_KEY,
|
|
|
|
+ DFSConfigKeys.DFS_NAMENODE_AVOID_SLOW_DATANODE_FOR_READ_DEFAULT);
|
|
this.readConsiderLoad = conf.getBoolean(
|
|
this.readConsiderLoad = conf.getBoolean(
|
|
DFSConfigKeys.DFS_NAMENODE_READ_CONSIDERLOAD_KEY,
|
|
DFSConfigKeys.DFS_NAMENODE_READ_CONSIDERLOAD_KEY,
|
|
DFSConfigKeys.DFS_NAMENODE_READ_CONSIDERLOAD_DEFAULT);
|
|
DFSConfigKeys.DFS_NAMENODE_READ_CONSIDERLOAD_DEFAULT);
|
|
@@ -389,7 +387,7 @@ public class DatanodeManager {
|
|
public void run() {
|
|
public void run() {
|
|
while (true) {
|
|
while (true) {
|
|
try {
|
|
try {
|
|
- slowNodesSet = getSlowPeers();
|
|
|
|
|
|
+ slowNodesUuidSet = getSlowPeersUuidSet();
|
|
} catch (Exception e) {
|
|
} catch (Exception e) {
|
|
LOG.error("Failed to collect slow peers", e);
|
|
LOG.error("Failed to collect slow peers", e);
|
|
}
|
|
}
|
|
@@ -509,12 +507,16 @@ public class DatanodeManager {
|
|
return datanode.isDecommissioned() || datanode.isEnteringMaintenance() ||
|
|
return datanode.isDecommissioned() || datanode.isEnteringMaintenance() ||
|
|
(avoidStaleDataNodesForRead && datanode.isStale(staleInterval));
|
|
(avoidStaleDataNodesForRead && datanode.isStale(staleInterval));
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ private boolean isSlowNode(String dnUuid) {
|
|
|
|
+ return avoidSlowDataNodesForRead && slowNodesUuidSet.contains(dnUuid);
|
|
|
|
+ }
|
|
|
|
|
|
/**
|
|
/**
|
|
* Sort the non-striped located blocks by the distance to the target host.
|
|
* Sort the non-striped located blocks by the distance to the target host.
|
|
*
|
|
*
|
|
- * For striped blocks, it will only move decommissioned/stale nodes to the
|
|
|
|
- * bottom. For example, assume we have storage list:
|
|
|
|
|
|
+ * For striped blocks, it will only move decommissioned/stale/slow
|
|
|
|
+ * nodes to the bottom. For example, assume we have storage list:
|
|
* d0, d1, d2, d3, d4, d5, d6, d7, d8, d9
|
|
* d0, d1, d2, d3, d4, d5, d6, d7, d8, d9
|
|
* mapping to block indices:
|
|
* mapping to block indices:
|
|
* 0, 1, 2, 3, 4, 5, 6, 7, 8, 2
|
|
* 0, 1, 2, 3, 4, 5, 6, 7, 8, 2
|
|
@@ -526,8 +528,11 @@ public class DatanodeManager {
|
|
*/
|
|
*/
|
|
public void sortLocatedBlocks(final String targetHost,
|
|
public void sortLocatedBlocks(final String targetHost,
|
|
final List<LocatedBlock> locatedBlocks) {
|
|
final List<LocatedBlock> locatedBlocks) {
|
|
- Comparator<DatanodeInfo> comparator = avoidStaleDataNodesForRead ?
|
|
|
|
- new DFSUtil.ServiceAndStaleComparator(staleInterval) :
|
|
|
|
|
|
+ Comparator<DatanodeInfo> comparator =
|
|
|
|
+ avoidStaleDataNodesForRead || avoidSlowDataNodesForRead ?
|
|
|
|
+ new DFSUtil.StaleAndSlowComparator(
|
|
|
|
+ avoidStaleDataNodesForRead, staleInterval,
|
|
|
|
+ avoidSlowDataNodesForRead, slowNodesUuidSet) :
|
|
new DFSUtil.ServiceComparator();
|
|
new DFSUtil.ServiceComparator();
|
|
// sort located block
|
|
// sort located block
|
|
for (LocatedBlock lb : locatedBlocks) {
|
|
for (LocatedBlock lb : locatedBlocks) {
|
|
@@ -540,7 +545,8 @@ public class DatanodeManager {
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
/**
|
|
- * Move decommissioned/stale datanodes to the bottom. After sorting it will
|
|
|
|
|
|
+ * Move decommissioned/entering_maintenance/stale/slow
|
|
|
|
+ * datanodes to the bottom. After sorting it will
|
|
* update block indices and block tokens respectively.
|
|
* update block indices and block tokens respectively.
|
|
*
|
|
*
|
|
* @param lb located striped block
|
|
* @param lb located striped block
|
|
@@ -571,8 +577,9 @@ public class DatanodeManager {
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
/**
|
|
- * Move decommissioned/entering_maintenance/stale datanodes to the bottom.
|
|
|
|
- * Also, sort nodes by network distance.
|
|
|
|
|
|
+ * Move decommissioned/entering_maintenance/stale/slow
|
|
|
|
+ * datanodes to the bottom. Also, sort nodes by network
|
|
|
|
+ * distance.
|
|
*
|
|
*
|
|
* @param lb located block
|
|
* @param lb located block
|
|
* @param targetHost target host
|
|
* @param targetHost target host
|
|
@@ -602,12 +609,15 @@ public class DatanodeManager {
|
|
}
|
|
}
|
|
|
|
|
|
DatanodeInfoWithStorage[] di = lb.getLocations();
|
|
DatanodeInfoWithStorage[] di = lb.getLocations();
|
|
- // Move decommissioned/entering_maintenance/stale datanodes to the bottom
|
|
|
|
|
|
+ // Move decommissioned/entering_maintenance/stale/slow
|
|
|
|
+ // datanodes to the bottom
|
|
Arrays.sort(di, comparator);
|
|
Arrays.sort(di, comparator);
|
|
|
|
|
|
// Sort nodes by network distance only for located blocks
|
|
// Sort nodes by network distance only for located blocks
|
|
int lastActiveIndex = di.length - 1;
|
|
int lastActiveIndex = di.length - 1;
|
|
- while (lastActiveIndex > 0 && isInactive(di[lastActiveIndex])) {
|
|
|
|
|
|
+ while (lastActiveIndex > 0 && (
|
|
|
|
+ isSlowNode(di[lastActiveIndex].getDatanodeUuid()) ||
|
|
|
|
+ isInactive(di[lastActiveIndex]))) {
|
|
--lastActiveIndex;
|
|
--lastActiveIndex;
|
|
}
|
|
}
|
|
int activeLen = lastActiveIndex + 1;
|
|
int activeLen = lastActiveIndex + 1;
|
|
@@ -2083,10 +2093,10 @@ public class DatanodeManager {
|
|
* Returns all tracking slow peers.
|
|
* Returns all tracking slow peers.
|
|
* @return
|
|
* @return
|
|
*/
|
|
*/
|
|
- public Set<Node> getSlowPeers() {
|
|
|
|
- Set<Node> slowPeersSet = Sets.newConcurrentHashSet();
|
|
|
|
|
|
+ public Set<String> getSlowPeersUuidSet() {
|
|
|
|
+ Set<String> slowPeersUuidSet = Sets.newConcurrentHashSet();
|
|
if (slowPeerTracker == null) {
|
|
if (slowPeerTracker == null) {
|
|
- return slowPeersSet;
|
|
|
|
|
|
+ return slowPeersUuidSet;
|
|
}
|
|
}
|
|
ArrayList<String> slowNodes =
|
|
ArrayList<String> slowNodes =
|
|
slowPeerTracker.getSlowNodes(maxSlowPeerReportNodes);
|
|
slowPeerTracker.getSlowNodes(maxSlowPeerReportNodes);
|
|
@@ -2099,18 +2109,18 @@ public class DatanodeManager {
|
|
DatanodeDescriptor datanodeByHost =
|
|
DatanodeDescriptor datanodeByHost =
|
|
host2DatanodeMap.getDatanodeByHost(ipAddr);
|
|
host2DatanodeMap.getDatanodeByHost(ipAddr);
|
|
if (datanodeByHost != null) {
|
|
if (datanodeByHost != null) {
|
|
- slowPeersSet.add(datanodeByHost);
|
|
|
|
|
|
+ slowPeersUuidSet.add(datanodeByHost.getDatanodeUuid());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
- return slowPeersSet;
|
|
|
|
|
|
+ return slowPeersUuidSet;
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
/**
|
|
- * Returns all tracking slow peers.
|
|
|
|
|
|
+ * Returns all tracking slow datanodes uuids.
|
|
* @return
|
|
* @return
|
|
*/
|
|
*/
|
|
- public static Set<Node> getSlowNodes() {
|
|
|
|
- return slowNodesSet;
|
|
|
|
|
|
+ public static Set<String> getSlowNodesUuidSet() {
|
|
|
|
+ return slowNodesUuidSet;
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
/**
|
|
@@ -2128,6 +2138,12 @@ public class DatanodeManager {
|
|
public SlowDiskTracker getSlowDiskTracker() {
|
|
public SlowDiskTracker getSlowDiskTracker() {
|
|
return slowDiskTracker;
|
|
return slowDiskTracker;
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ @VisibleForTesting
|
|
|
|
+ public void addSlowPeers(String dnUuid) {
|
|
|
|
+ slowNodesUuidSet.add(dnUuid);
|
|
|
|
+ }
|
|
|
|
+
|
|
/**
|
|
/**
|
|
* Retrieve information about slow disks as a JSON.
|
|
* Retrieve information about slow disks as a JSON.
|
|
* Returns null if we are not tracking slow disks.
|
|
* Returns null if we are not tracking slow disks.
|