HDFS-14758. Make lease hard limit configurable and reduce the default.

Contributed by hemanthboyina.

(cherry picked from commit 9b8a78d97b)

Conflicts:
	hadoop-hdfs-project/hadoop-hdfs-client/src/main/java/org/apache/hadoop/hdfs/client/impl/DfsClientConf.java
	hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/DFSConfigKeys.java
	hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/LeaseManager.java
	hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/TestFileAppend4.java
This commit is contained in:
Kihwal Lee 2020-02-11 14:50:10 -06:00
parent edad6f1d0f
commit f1840669cf
12 changed files with 48 additions and 23 deletions

View File

@ -572,10 +572,10 @@ public class DFSClient implements java.io.Closeable, RemotePeerFactory,
} catch (IOException e) { } catch (IOException e) {
// Abort if the lease has already expired. // Abort if the lease has already expired.
final long elapsed = Time.monotonicNow() - getLastLeaseRenewal(); final long elapsed = Time.monotonicNow() - getLastLeaseRenewal();
if (elapsed > HdfsConstants.LEASE_HARDLIMIT_PERIOD) { if (elapsed > dfsClientConf.getleaseHardLimitPeriod()) {
LOG.warn("Failed to renew lease for " + clientName + " for " LOG.warn("Failed to renew lease for " + clientName + " for "
+ (elapsed/1000) + " seconds (>= hard-limit =" + (elapsed/1000) + " seconds (>= hard-limit ="
+ (HdfsConstants.LEASE_HARDLIMIT_PERIOD / 1000) + " seconds.) " + (dfsClientConf.getleaseHardLimitPeriod() / 1000) + " seconds.) "
+ "Closing all files being written ...", e); + "Closing all files being written ...", e);
closeAllFilesBeingWritten(true); closeAllFilesBeingWritten(true);
} else { } else {

View File

@ -200,6 +200,9 @@ public interface HdfsClientConfigKeys {
String DFS_PROVIDED_ALIASMAP_INMEMORY_RPC_ADDRESS = String DFS_PROVIDED_ALIASMAP_INMEMORY_RPC_ADDRESS =
"dfs.provided.aliasmap.inmemory.dnrpc-address"; "dfs.provided.aliasmap.inmemory.dnrpc-address";
String DFS_LEASE_HARDLIMIT_KEY = "dfs.namenode.lease-hard-limit-sec";
long DFS_LEASE_HARDLIMIT_DEFAULT = 20 * 60;
/** /**
* These are deprecated config keys to client code. * These are deprecated config keys to client code.
*/ */

View File

@ -146,6 +146,7 @@ public class DfsClientConf {
private final int stripedReadThreadpoolSize; private final int stripedReadThreadpoolSize;
private final boolean dataTransferTcpNoDelay; private final boolean dataTransferTcpNoDelay;
private final long leaseHardLimitPeriod;
public DfsClientConf(Configuration conf) { public DfsClientConf(Configuration conf) {
// The hdfsTimeout is currently the same as the ipc timeout // The hdfsTimeout is currently the same as the ipc timeout
@ -273,6 +274,10 @@ public class DfsClientConf {
HdfsClientConfigKeys.StripedRead.THREADPOOL_SIZE_KEY + HdfsClientConfigKeys.StripedRead.THREADPOOL_SIZE_KEY +
" must be greater than 0."); " must be greater than 0.");
replicaAccessorBuilderClasses = loadReplicaAccessorBuilderClasses(conf); replicaAccessorBuilderClasses = loadReplicaAccessorBuilderClasses(conf);
leaseHardLimitPeriod =
conf.getLong(HdfsClientConfigKeys.DFS_LEASE_HARDLIMIT_KEY,
HdfsClientConfigKeys.DFS_LEASE_HARDLIMIT_DEFAULT) * 1000;
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@ -595,6 +600,13 @@ public class DfsClientConf {
return stripedReadThreadpoolSize; return stripedReadThreadpoolSize;
} }
/**
* @return the leaseHardLimitPeriod
*/
public long getleaseHardLimitPeriod() {
return leaseHardLimitPeriod;
}
/** /**
* @return the replicaAccessorBuilderClasses * @return the replicaAccessorBuilderClasses
*/ */

View File

@ -111,17 +111,6 @@ public final class HdfsConstants {
* lease, another client can preempt the lease. * lease, another client can preempt the lease.
*/ */
public static final long LEASE_SOFTLIMIT_PERIOD = 60 * 1000; public static final long LEASE_SOFTLIMIT_PERIOD = 60 * 1000;
/**
* For a HDFS client to write to a file, a lease is granted; During the lease
* period, no other client can write to the file. The writing client can
* periodically renew the lease. When the file is closed, the lease is
* revoked. The lease duration is bound by a
* {@link HdfsConstants#LEASE_SOFTLIMIT_PERIOD soft limit} and this hard
* limit. If after the hard limit expires and the client has failed to renew
* the lease, HDFS assumes that the client has quit and will automatically
* close the file on behalf of the writer, and recover the lease.
*/
public static final long LEASE_HARDLIMIT_PERIOD = 60 * LEASE_SOFTLIMIT_PERIOD;
// SafeMode actions // SafeMode actions
public enum SafeModeAction { public enum SafeModeAction {

View File

@ -1676,4 +1676,8 @@ public class DFSConfigKeys extends CommonConfigurationKeys {
public static final long DFS_CLIENT_KEY_PROVIDER_CACHE_EXPIRY_DEFAULT = public static final long DFS_CLIENT_KEY_PROVIDER_CACHE_EXPIRY_DEFAULT =
HdfsClientConfigKeys.DFS_CLIENT_KEY_PROVIDER_CACHE_EXPIRY_DEFAULT; HdfsClientConfigKeys.DFS_CLIENT_KEY_PROVIDER_CACHE_EXPIRY_DEFAULT;
public static final String DFS_LEASE_HARDLIMIT_KEY =
HdfsClientConfigKeys.DFS_LEASE_HARDLIMIT_KEY;
public static final long DFS_LEASE_HARDLIMIT_DEFAULT =
HdfsClientConfigKeys.DFS_LEASE_HARDLIMIT_DEFAULT;
} }

View File

@ -40,7 +40,9 @@ import com.google.common.collect.Lists;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.apache.hadoop.classification.InterfaceAudience; import org.apache.hadoop.classification.InterfaceAudience;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.BatchedRemoteIterator.BatchedListEntries; import org.apache.hadoop.fs.BatchedRemoteIterator.BatchedListEntries;
import org.apache.hadoop.hdfs.DFSConfigKeys;
import org.apache.hadoop.hdfs.protocol.HdfsConstants; import org.apache.hadoop.hdfs.protocol.HdfsConstants;
import org.apache.hadoop.hdfs.protocol.OpenFileEntry; import org.apache.hadoop.hdfs.protocol.OpenFileEntry;
import org.apache.hadoop.hdfs.protocol.OpenFilesIterator; import org.apache.hadoop.hdfs.protocol.OpenFilesIterator;
@ -82,7 +84,7 @@ public class LeaseManager {
.getName()); .getName());
private final FSNamesystem fsnamesystem; private final FSNamesystem fsnamesystem;
private long softLimit = HdfsConstants.LEASE_SOFTLIMIT_PERIOD; private long softLimit = HdfsConstants.LEASE_SOFTLIMIT_PERIOD;
private long hardLimit = HdfsConstants.LEASE_HARDLIMIT_PERIOD; private long hardLimit;
static final int INODE_FILTER_WORKER_COUNT_MAX = 4; static final int INODE_FILTER_WORKER_COUNT_MAX = 4;
static final int INODE_FILTER_WORKER_TASK_MIN = 512; static final int INODE_FILTER_WORKER_TASK_MIN = 512;
private long lastHolderUpdateTime; private long lastHolderUpdateTime;
@ -110,7 +112,10 @@ public class LeaseManager {
private volatile boolean shouldRunMonitor; private volatile boolean shouldRunMonitor;
LeaseManager(FSNamesystem fsnamesystem) { LeaseManager(FSNamesystem fsnamesystem) {
Configuration conf = new Configuration();
this.fsnamesystem = fsnamesystem; this.fsnamesystem = fsnamesystem;
this.hardLimit = conf.getLong(DFSConfigKeys.DFS_LEASE_HARDLIMIT_KEY,
DFSConfigKeys.DFS_LEASE_HARDLIMIT_DEFAULT) * 1000;
updateInternalLeaseHolder(); updateInternalLeaseHolder();
} }

View File

@ -5387,4 +5387,12 @@
octal or symbolic. octal or symbolic.
</description> </description>
</property> </property>
<property>
<name>dfs.namenode.lease-hard-limit-sec</name>
<value>1200</value>
<description>
Determines the namenode automatic lease recovery interval in seconds.
</description>
</property>
</configuration> </configuration>

View File

@ -41,7 +41,6 @@ import org.apache.hadoop.fs.Path;
import org.apache.hadoop.hdfs.client.HdfsClientConfigKeys; import org.apache.hadoop.hdfs.client.HdfsClientConfigKeys;
import org.apache.hadoop.hdfs.protocol.DatanodeInfo; import org.apache.hadoop.hdfs.protocol.DatanodeInfo;
import org.apache.hadoop.hdfs.protocol.ExtendedBlock; import org.apache.hadoop.hdfs.protocol.ExtendedBlock;
import org.apache.hadoop.hdfs.protocol.HdfsConstants;
import org.apache.hadoop.hdfs.protocol.LocatedBlocks; import org.apache.hadoop.hdfs.protocol.LocatedBlocks;
import org.apache.hadoop.hdfs.server.datanode.DataNode; import org.apache.hadoop.hdfs.server.datanode.DataNode;
import org.apache.hadoop.hdfs.server.namenode.FSDirectory; import org.apache.hadoop.hdfs.server.namenode.FSDirectory;
@ -108,7 +107,9 @@ public class TestFileAppend4 {
// set the soft limit to be 1 second so that the // set the soft limit to be 1 second so that the
// namenode triggers lease recovery upon append request // namenode triggers lease recovery upon append request
cluster.setLeasePeriod(1000, HdfsConstants.LEASE_HARDLIMIT_PERIOD); cluster.setLeasePeriod(1,
conf.getLong(DFSConfigKeys.DFS_LEASE_HARDLIMIT_KEY,
DFSConfigKeys.DFS_LEASE_HARDLIMIT_DEFAULT));
// Trying recovery // Trying recovery
int tries = 60; int tries = 60;

View File

@ -114,9 +114,10 @@ public class TestLease {
Assert.fail("Write failed."); Assert.fail("Write failed.");
} }
long hardlimit = conf.getLong(DFSConfigKeys.DFS_LEASE_HARDLIMIT_KEY,
DFSConfigKeys.DFS_LEASE_HARDLIMIT_DEFAULT) * 1000;
// make it look like the hard limit has been exceeded. // make it look like the hard limit has been exceeded.
dfs.lastLeaseRenewal = Time.monotonicNow() dfs.lastLeaseRenewal = Time.monotonicNow() - hardlimit - 1000;
- HdfsConstants.LEASE_HARDLIMIT_PERIOD - 1000;
dfs.renewLease(); dfs.renewLease();
// this should not work. // this should not work.

View File

@ -407,10 +407,10 @@ public class TestLeaseRecovery2 {
Map<String, String []> u2g_map = new HashMap<String, String []>(1); Map<String, String []> u2g_map = new HashMap<String, String []>(1);
u2g_map.put(fakeUsername, new String[] {fakeGroup}); u2g_map.put(fakeUsername, new String[] {fakeGroup});
DFSTestUtil.updateConfWithFakeGroupMapping(conf, u2g_map); DFSTestUtil.updateConfWithFakeGroupMapping(conf, u2g_map);
long hardlimit = conf.getLong(DFSConfigKeys.DFS_LEASE_HARDLIMIT_KEY,
DFSConfigKeys.DFS_LEASE_HARDLIMIT_DEFAULT) * 1000;
// Reset default lease periods // Reset default lease periods
cluster.setLeasePeriod(HdfsConstants.LEASE_SOFTLIMIT_PERIOD, cluster.setLeasePeriod(HdfsConstants.LEASE_SOFTLIMIT_PERIOD, hardlimit);
HdfsConstants.LEASE_HARDLIMIT_PERIOD);
//create a file //create a file
// create a random file name // create a random file name
String filestr = "/foo" + AppendTestUtil.nextInt(); String filestr = "/foo" + AppendTestUtil.nextInt();

View File

@ -659,7 +659,8 @@ public class TestFileTruncate {
NameNodeAdapter.getLeaseManager(cluster.getNamesystem()) NameNodeAdapter.getLeaseManager(cluster.getNamesystem())
.setLeasePeriod(HdfsConstants.LEASE_SOFTLIMIT_PERIOD, .setLeasePeriod(HdfsConstants.LEASE_SOFTLIMIT_PERIOD,
HdfsConstants.LEASE_HARDLIMIT_PERIOD); conf.getLong(DFSConfigKeys.DFS_LEASE_HARDLIMIT_KEY,
DFSConfigKeys.DFS_LEASE_HARDLIMIT_DEFAULT) * 1000);
checkFullFile(p, newLength, contents); checkFullFile(p, newLength, contents);
fs.delete(p, false); fs.delete(p, false);

View File

@ -304,7 +304,8 @@ public class TestINodeFileUnderConstructionWithSnapshot {
} }
} finally { } finally {
NameNodeAdapter.setLeasePeriod(fsn, HdfsConstants.LEASE_SOFTLIMIT_PERIOD, NameNodeAdapter.setLeasePeriod(fsn, HdfsConstants.LEASE_SOFTLIMIT_PERIOD,
HdfsConstants.LEASE_HARDLIMIT_PERIOD); conf.getLong(DFSConfigKeys.DFS_LEASE_HARDLIMIT_KEY,
DFSConfigKeys.DFS_LEASE_HARDLIMIT_DEFAULT) * 1000);
} }
} }
} }