Skip to content

Commit

Permalink
YARN-10084. Allow inheritance of max app lifetime / default app lifet…
Browse files Browse the repository at this point in the history
…ime. Contributed by Eric Payne.
  • Loading branch information
ericbadger committed Jan 29, 2020
1 parent 1643cfd commit e578e52
Show file tree
Hide file tree
Showing 5 changed files with 322 additions and 31 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
import org.apache.hadoop.yarn.api.records.ResourceInformation;
import org.apache.hadoop.yarn.conf.YarnConfiguration;
import org.apache.hadoop.yarn.exceptions.YarnException;
import org.apache.hadoop.yarn.exceptions.YarnRuntimeException;
import org.apache.hadoop.yarn.factories.RecordFactory;
import org.apache.hadoop.yarn.factory.providers.RecordFactoryProvider;
import org.apache.hadoop.yarn.security.AccessRequest;
Expand Down Expand Up @@ -116,6 +117,15 @@ public abstract class AbstractCSQueue implements CSQueue {

QueueResourceQuotas queueResourceQuotas;

// -1 indicates lifetime is disabled
private volatile long maxApplicationLifetime = -1;

private volatile long defaultApplicationLifetime = -1;

// Indicates if this queue's default lifetime was set by a config property,
// either at this level or anywhere in the queue's hierarchy.
private volatile boolean defaultAppLifetimeWasSpecifiedInConfig = false;

protected enum CapacityConfigType {
NONE, PERCENTAGE, ABSOLUTE_RESOURCE
};
Expand Down Expand Up @@ -425,6 +435,19 @@ protected void setupQueueConfigs(Resource clusterResource,
configuration.getMultiNodesSortingAlgorithmPolicy(getQueuePath()));

this.userWeights = getUserWeightsFromHierarchy(configuration);

maxApplicationLifetime = getInheritedMaxAppLifetime(this, configuration);
defaultApplicationLifetime =
getInheritedDefaultAppLifetime(this, configuration,
maxApplicationLifetime);
if (maxApplicationLifetime > 0 &&
defaultApplicationLifetime > maxApplicationLifetime) {
throw new YarnRuntimeException(
"Default lifetime " + defaultApplicationLifetime
+ " can't exceed maximum lifetime " + maxApplicationLifetime);
}
defaultApplicationLifetime = defaultApplicationLifetime > 0
? defaultApplicationLifetime : maxApplicationLifetime;
} finally {
writeLock.unlock();
}
Expand Down Expand Up @@ -860,6 +883,68 @@ private boolean isQueueHierarchyPreemptionDisabled(CSQueue q,
parentQ.getPreemptionDisabled());
}

private long getInheritedMaxAppLifetime(CSQueue q,
CapacitySchedulerConfiguration conf) {
CSQueue parentQ = q.getParent();
long maxAppLifetime = conf.getMaximumLifetimePerQueue(q.getQueuePath());

// If q is the root queue, then get max app lifetime from conf.
if (parentQ == null) {
return maxAppLifetime;
}

// If this is not the root queue, get this queue's max app lifetime
// from the conf. The parent's max app lifetime will be used if it's
// not set for this queue.
// A value of 0 will override the parent's value and means no max lifetime.
// A negative value means that the parent's max should be used.
long parentsMaxAppLifetime = getParent().getMaximumApplicationLifetime();
return (maxAppLifetime >= 0) ? maxAppLifetime : parentsMaxAppLifetime;
}

private long getInheritedDefaultAppLifetime(CSQueue q,
CapacitySchedulerConfiguration conf, long myMaxAppLifetime) {
CSQueue parentQ = q.getParent();
long defaultAppLifetime = conf.getDefaultLifetimePerQueue(getQueuePath());
defaultAppLifetimeWasSpecifiedInConfig =
(defaultAppLifetime >= 0
|| (parentQ != null &&
parentQ.getDefaultAppLifetimeWasSpecifiedInConfig()));

// If q is the root queue, then get default app lifetime from conf.
if (parentQ == null) {
return defaultAppLifetime;
}

// If this is not the root queue, get the parent's default app lifetime. The
// parent's default app lifetime will be used if not set for this queue.
long parentsDefaultAppLifetime =
getParent().getDefaultApplicationLifetime();

// Negative value indicates default lifetime was not set at this level.
// If default lifetime was not set at this level, calculate it based on
// parent's default lifetime or current queue's max lifetime.
if (defaultAppLifetime < 0) {
// If default lifetime was not set at this level but was set somewhere in
// the parent's hierarchy, set default lifetime to parent queue's default
// only if parent queue's lifetime is less than current queueu's max
// lifetime. Otherwise, use current queue's max lifetime value for its
// default lifetime.
if (defaultAppLifetimeWasSpecifiedInConfig) {
if (parentsDefaultAppLifetime <= myMaxAppLifetime) {
defaultAppLifetime = parentsDefaultAppLifetime;
} else {
defaultAppLifetime = myMaxAppLifetime;
}
} else {
// Default app lifetime value was not set anywhere in this queue's
// hierarchy. Use current queue's max lifetime as its default.
defaultAppLifetime = myMaxAppLifetime;
}
} // else if >= 0, default lifetime was set at this level. Just use it.
return defaultAppLifetime;
}

/**
* The specified queue is intra-queue preemptable if
* 1) system-wide intra-queue preemption is turned on
Expand Down Expand Up @@ -1317,4 +1402,16 @@ public String getMultiNodeSortingPolicyName() {
public void setMultiNodeSortingPolicyName(String policyName) {
this.multiNodeSortingPolicyName = policyName;
}

public long getMaximumApplicationLifetime() {
return maxApplicationLifetime;
}

public long getDefaultApplicationLifetime() {
return defaultApplicationLifetime;
}

public boolean getDefaultAppLifetimeWasSpecifiedInConfig() {
return defaultAppLifetimeWasSpecifiedInConfig;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -449,4 +449,26 @@ public void validateSubmitApplication(ApplicationId applicationId,
* @return policy name
*/
String getMultiNodeSortingPolicyName();

/**
* Get the maximum lifetime in seconds of an application which is submitted to
* this queue. Apps can set their own lifetime timeout up to this value.
* @return max lifetime in seconds
*/
long getMaximumApplicationLifetime();

/**
* Get the default lifetime in seconds of an application which is submitted to
* this queue. If an app doesn't specify its own timeout when submitted, this
* value will be used.
* @return default app lifetime
*/
long getDefaultApplicationLifetime();

/**
* Get the indicator of whether or not the default application lifetime was
* set by a config property or was calculated by the capacity scheduler.
* @return indicator whether set or calculated
*/
boolean getDefaultAppLifetimeWasSpecifiedInConfig();
}
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@
import org.apache.hadoop.yarn.api.records.QueueState;
import org.apache.hadoop.yarn.api.records.QueueUserACLInfo;
import org.apache.hadoop.yarn.api.records.Resource;
import org.apache.hadoop.yarn.exceptions.YarnRuntimeException;
import org.apache.hadoop.yarn.factories.RecordFactory;
import org.apache.hadoop.yarn.factory.providers.RecordFactoryProvider;
import org.apache.hadoop.yarn.nodelabels.CommonNodeLabelsManager;
Expand Down Expand Up @@ -130,10 +129,6 @@ public class LeafQueue extends AbstractCSQueue {
List<AppPriorityACLGroup> priorityAcls =
new ArrayList<AppPriorityACLGroup>();

// -1 indicates lifetime is disabled
private volatile long maxApplicationLifetime = -1;
private volatile long defaultApplicationLifetime = -1;

@SuppressWarnings({ "unchecked", "rawtypes" })
public LeafQueue(CapacitySchedulerContext cs,
String queueName, CSQueue parent, CSQueue old) throws IOException {
Expand Down Expand Up @@ -256,19 +251,6 @@ protected void setupQueueConfigs(Resource clusterResource,
defaultAppPriorityPerQueue = Priority.newInstance(
conf.getDefaultApplicationPriorityConfPerQueue(getQueuePath()));

maxApplicationLifetime =
conf.getMaximumLifetimePerQueue((getQueuePath()));
defaultApplicationLifetime =
conf.getDefaultLifetimePerQueue((getQueuePath()));
if (maxApplicationLifetime > 0 &&
defaultApplicationLifetime > maxApplicationLifetime) {
throw new YarnRuntimeException(
"Default lifetime" + defaultApplicationLifetime
+ " can't exceed maximum lifetime " + maxApplicationLifetime);
}
defaultApplicationLifetime = defaultApplicationLifetime > 0
? defaultApplicationLifetime : maxApplicationLifetime;

// Validate leaf queue's user's weights.
int queueUL = Math.min(100, conf.getUserLimit(getQueuePath()));
for (Entry<String, Float> e : getUserWeights().entrySet()) {
Expand Down Expand Up @@ -329,9 +311,9 @@ protected void setupQueueConfigs(Resource clusterResource,
+ reservationsContinueLooking + "\n" + "preemptionDisabled = "
+ getPreemptionDisabled() + "\n" + "defaultAppPriorityPerQueue = "
+ defaultAppPriorityPerQueue + "\npriority = " + priority
+ "\nmaxLifetime = " + maxApplicationLifetime + " seconds"
+ "\ndefaultLifetime = "
+ defaultApplicationLifetime + " seconds");
+ "\nmaxLifetime = " + getMaximumApplicationLifetime()
+ " seconds" + "\ndefaultLifetime = "
+ getDefaultApplicationLifetime() + " seconds");
} finally {
writeLock.unlock();
}
Expand Down Expand Up @@ -2209,14 +2191,6 @@ static class CachedUserLimit {
}
}

public long getMaximumApplicationLifetime() {
return maxApplicationLifetime;
}

public long getDefaultApplicationLifetime() {
return defaultApplicationLifetime;
}

private void updateQueuePreemptionMetrics(RMContainer rmc) {
final long usedMillis = rmc.getFinishTime() - rmc.getCreationTime();
final long usedSeconds = usedMillis / DateUtils.MILLIS_PER_SECOND;
Expand Down
Loading

0 comments on commit e578e52

Please sign in to comment.