This is an automated email from the ASF dual-hosted git repository.

hutran pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-gobblin.git


The following commit(s) were added to refs/heads/master by this push:
     new c41283f  [GOBBLIN-770] Add JVM configuration to avoid exhausting YARN 
container memory
c41283f is described below

commit c41283fb39a1e58799923eb5e188df1fbbf7bd8d
Author: Hung Tran <[email protected]>
AuthorDate: Wed May 15 14:08:53 2019 -0700

    [GOBBLIN-770] Add JVM configuration to avoid exhausting YARN container 
memory
    
    Closes #2634 from htran1/yarn_memory_config
---
 .../gobblin/yarn/GobblinYarnAppLauncher.java       | 30 +++++++++++++++++++---
 .../gobblin/yarn/GobblinYarnConfigurationKeys.java | 14 ++++++++++
 .../java/org/apache/gobblin/yarn/YarnService.java  | 25 ++++++++++++++++--
 .../gobblin/yarn/GobblinYarnAppLauncherTest.java   |  8 ++++++
 .../org/apache/gobblin/yarn/YarnServiceTest.java   | 21 +++++++++++++++
 .../test/resources/GobblinYarnAppLauncherTest.conf |  3 +++
 6 files changed, 96 insertions(+), 5 deletions(-)

diff --git 
a/gobblin-yarn/src/main/java/org/apache/gobblin/yarn/GobblinYarnAppLauncher.java
 
b/gobblin-yarn/src/main/java/org/apache/gobblin/yarn/GobblinYarnAppLauncher.java
index 5370375..8288604 100644
--- 
a/gobblin-yarn/src/main/java/org/apache/gobblin/yarn/GobblinYarnAppLauncher.java
+++ 
b/gobblin-yarn/src/main/java/org/apache/gobblin/yarn/GobblinYarnAppLauncher.java
@@ -71,6 +71,7 @@ import org.slf4j.LoggerFactory;
 
 import com.google.common.annotations.VisibleForTesting;
 import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
 import com.google.common.base.Splitter;
 import com.google.common.base.Strings;
 import com.google.common.base.Throwables;
@@ -201,6 +202,10 @@ public class GobblinYarnAppLauncher {
 
   private final boolean emailNotificationOnShutdown;
 
+  private final int appMasterMemoryMbs;
+  private final int jvmMemoryOverheadMbs;
+  private final double jvmMemoryXmxRatio;
+
   public GobblinYarnAppLauncher(Config config, YarnConfiguration 
yarnConfiguration) throws IOException {
     this.config = config;
 
@@ -238,6 +243,24 @@ public class GobblinYarnAppLauncher {
 
     this.emailNotificationOnShutdown =
         
config.getBoolean(GobblinYarnConfigurationKeys.EMAIL_NOTIFICATION_ON_SHUTDOWN_KEY);
+
+    this.appMasterMemoryMbs = 
this.config.getInt(GobblinYarnConfigurationKeys.APP_MASTER_MEMORY_MBS_KEY);
+
+    this.jvmMemoryXmxRatio = ConfigUtils.getDouble(this.config,
+        GobblinYarnConfigurationKeys.APP_MASTER_JVM_MEMORY_XMX_RATIO_KEY,
+        GobblinYarnConfigurationKeys.DEFAULT_APP_MASTER_JVM_MEMORY_XMX_RATIO);
+
+    Preconditions.checkArgument(this.jvmMemoryXmxRatio >= 0 && 
this.jvmMemoryXmxRatio <= 1,
+        GobblinYarnConfigurationKeys.APP_MASTER_JVM_MEMORY_XMX_RATIO_KEY + " 
must be between 0 and 1 inclusive");
+
+    this.jvmMemoryOverheadMbs = ConfigUtils.getInt(this.config,
+        GobblinYarnConfigurationKeys.APP_MASTER_JVM_MEMORY_OVERHEAD_MBS_KEY,
+        
GobblinYarnConfigurationKeys.DEFAULT_APP_MASTER_JVM_MEMORY_OVERHEAD_MBS);
+
+    Preconditions.checkArgument(this.jvmMemoryOverheadMbs < 
this.appMasterMemoryMbs * this.jvmMemoryXmxRatio,
+        GobblinYarnConfigurationKeys.CONTAINER_JVM_MEMORY_OVERHEAD_MBS_KEY + " 
cannot be more than "
+            + GobblinYarnConfigurationKeys.CONTAINER_MEMORY_MBS_KEY + " * "
+            + GobblinYarnConfigurationKeys.CONTAINER_JVM_MEMORY_XMX_RATIO_KEY);
   }
 
   /**
@@ -509,7 +532,7 @@ public class GobblinYarnAppLauncher {
   }
 
   private Resource prepareContainerResource(GetNewApplicationResponse 
newApplicationResponse) {
-    int memoryMbs = 
this.config.getInt(GobblinYarnConfigurationKeys.APP_MASTER_MEMORY_MBS_KEY);
+    int memoryMbs = this.appMasterMemoryMbs;
     int maximumMemoryCapacity = 
newApplicationResponse.getMaximumResourceCapability().getMemory();
     if (memoryMbs > maximumMemoryCapacity) {
       LOGGER.info(String.format("Specified AM memory [%d] is above the maximum 
memory capacity [%d] of the "
@@ -635,11 +658,12 @@ public class GobblinYarnAppLauncher {
     YarnHelixUtils.addFileAsLocalResource(this.fs, destFilePath, 
LocalResourceType.ARCHIVE, resourceMap);
   }
 
-  private String buildApplicationMasterCommand(int memoryMbs) {
+  @VisibleForTesting
+  protected String buildApplicationMasterCommand(int memoryMbs) {
     String appMasterClassName = GobblinApplicationMaster.class.getSimpleName();
     return new StringBuilder()
         
.append(ApplicationConstants.Environment.JAVA_HOME.$()).append("/bin/java")
-        .append(" -Xmx").append(memoryMbs).append("M")
+        .append(" -Xmx").append((int) (memoryMbs * this.jvmMemoryXmxRatio) - 
this.jvmMemoryOverheadMbs).append("M")
         .append(" ").append(JvmUtils.formatJvmArguments(this.appMasterJvmArgs))
         .append(" ").append(GobblinApplicationMaster.class.getName())
         .append(" 
--").append(GobblinClusterConfigurationKeys.APPLICATION_NAME_OPTION_NAME)
diff --git 
a/gobblin-yarn/src/main/java/org/apache/gobblin/yarn/GobblinYarnConfigurationKeys.java
 
b/gobblin-yarn/src/main/java/org/apache/gobblin/yarn/GobblinYarnConfigurationKeys.java
index 6098eae..7c80063 100644
--- 
a/gobblin-yarn/src/main/java/org/apache/gobblin/yarn/GobblinYarnConfigurationKeys.java
+++ 
b/gobblin-yarn/src/main/java/org/apache/gobblin/yarn/GobblinYarnConfigurationKeys.java
@@ -45,6 +45,13 @@ public class GobblinYarnConfigurationKeys {
   public static final String APP_MASTER_WORK_DIR_NAME = "appmaster";
   public static final String APP_MASTER_JVM_ARGS_KEY = GOBBLIN_YARN_PREFIX + 
"app.master.jvm.args";
   public static final String APP_MASTER_SERVICE_CLASSES = GOBBLIN_YARN_PREFIX 
+ "app.master.serviceClasses";
+  // Amount of overhead to subtract when computing the Xmx value. This is to 
account for non-heap memory, like metaspace
+  // and stack memory
+  public static final String APP_MASTER_JVM_MEMORY_OVERHEAD_MBS_KEY = 
GOBBLIN_YARN_PREFIX + "app.master.jvmMemoryOverheadMbs";
+  public static final int DEFAULT_APP_MASTER_JVM_MEMORY_OVERHEAD_MBS = 0;
+  // The ratio of the amount of Xmx to carve out of the container memory 
before adjusting for jvm memory overhead
+  public static final String APP_MASTER_JVM_MEMORY_XMX_RATIO_KEY = 
GOBBLIN_YARN_PREFIX + "app.master.jvmMemoryXmxRatio";
+  public static final double DEFAULT_APP_MASTER_JVM_MEMORY_XMX_RATIO = 1.0;
 
   // Gobblin Yarn container configuration properties.
   public static final String INITIAL_CONTAINERS_KEY = GOBBLIN_YARN_PREFIX + 
"initial.containers";
@@ -56,6 +63,13 @@ public class GobblinYarnConfigurationKeys {
   public static final String CONTAINER_WORK_DIR_NAME = "container";
   public static final String CONTAINER_JVM_ARGS_KEY = GOBBLIN_YARN_PREFIX + 
"container.jvm.args";
   public static final String CONTAINER_HOST_AFFINITY_ENABLED = 
GOBBLIN_YARN_PREFIX + "container.affinity.enabled";
+  // Amount of overhead to subtract when computing the Xmx value. This is to 
account for non-heap memory, like metaspace
+  // and stack memory
+  public static final String CONTAINER_JVM_MEMORY_OVERHEAD_MBS_KEY = 
GOBBLIN_YARN_PREFIX + "container.jvmMemoryOverheadMbs";
+  public static final int DEFAULT_CONTAINER_JVM_MEMORY_OVERHEAD_MBS = 0;
+  // The ratio of the amount of Xmx to carve out of the container memory 
before adjusting for jvm memory overhead
+  public static final String CONTAINER_JVM_MEMORY_XMX_RATIO_KEY = 
GOBBLIN_YARN_PREFIX + "container.jvmMemoryXmxRatio";
+  public static final double DEFAULT_CONTAINER_JVM_MEMORY_XMX_RATIO = 1.0;
 
   // Helix configuration properties.
   public static final String HELIX_INSTANCE_MAX_RETRIES = GOBBLIN_YARN_PREFIX 
+ "helix.instance.max.retries";
diff --git 
a/gobblin-yarn/src/main/java/org/apache/gobblin/yarn/YarnService.java 
b/gobblin-yarn/src/main/java/org/apache/gobblin/yarn/YarnService.java
index 614ac1f..f3d4e53 100644
--- a/gobblin-yarn/src/main/java/org/apache/gobblin/yarn/YarnService.java
+++ b/gobblin-yarn/src/main/java/org/apache/gobblin/yarn/YarnService.java
@@ -69,6 +69,7 @@ import org.slf4j.LoggerFactory;
 import com.google.common.annotations.VisibleForTesting;
 import com.google.common.base.Function;
 import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
 import com.google.common.base.Splitter;
 import com.google.common.base.Strings;
 import com.google.common.base.Throwables;
@@ -139,6 +140,8 @@ public class YarnService extends AbstractIdleService {
   private final int initialContainers;
   private final int requestedContainerMemoryMbs;
   private final int requestedContainerCores;
+  private final int jvmMemoryOverheadMbs;
+  private final double jvmMemoryXmxRatio;
   private final boolean containerHostAffinityEnabled;
 
   private final int helixInstanceMaxRetries;
@@ -231,6 +234,22 @@ public class YarnService extends AbstractIdleService {
     this.releasedContainerCache = 
CacheBuilder.newBuilder().expireAfterAccess(ConfigUtils.getInt(config,
         GobblinYarnConfigurationKeys.RELEASED_CONTAINERS_CACHE_EXPIRY_SECS,
         
GobblinYarnConfigurationKeys.DEFAULT_RELEASED_CONTAINERS_CACHE_EXPIRY_SECS), 
TimeUnit.SECONDS).build();
+
+    this.jvmMemoryXmxRatio = ConfigUtils.getDouble(this.config,
+        GobblinYarnConfigurationKeys.CONTAINER_JVM_MEMORY_XMX_RATIO_KEY,
+        GobblinYarnConfigurationKeys.DEFAULT_CONTAINER_JVM_MEMORY_XMX_RATIO);
+
+    Preconditions.checkArgument(this.jvmMemoryXmxRatio >= 0 && 
this.jvmMemoryXmxRatio <= 1,
+        GobblinYarnConfigurationKeys.CONTAINER_JVM_MEMORY_XMX_RATIO_KEY + " 
must be between 0 and 1 inclusive");
+
+    this.jvmMemoryOverheadMbs = ConfigUtils.getInt(this.config,
+        GobblinYarnConfigurationKeys.CONTAINER_JVM_MEMORY_OVERHEAD_MBS_KEY,
+        
GobblinYarnConfigurationKeys.DEFAULT_CONTAINER_JVM_MEMORY_OVERHEAD_MBS);
+
+    Preconditions.checkArgument(this.jvmMemoryOverheadMbs < 
this.requestedContainerMemoryMbs * this.jvmMemoryXmxRatio,
+        GobblinYarnConfigurationKeys.CONTAINER_JVM_MEMORY_OVERHEAD_MBS_KEY + " 
cannot be more than "
+            + GobblinYarnConfigurationKeys.CONTAINER_MEMORY_MBS_KEY + " * "
+            + GobblinYarnConfigurationKeys.CONTAINER_JVM_MEMORY_XMX_RATIO_KEY);
   }
 
   @SuppressWarnings("unused")
@@ -521,11 +540,13 @@ public class YarnService extends AbstractIdleService {
     }
   }
 
-  private String buildContainerCommand(Container container, String 
helixInstanceName) {
+  @VisibleForTesting
+  protected String buildContainerCommand(Container container, String 
helixInstanceName) {
     String containerProcessName = GobblinYarnTaskRunner.class.getSimpleName();
     return new StringBuilder()
         
.append(ApplicationConstants.Environment.JAVA_HOME.$()).append("/bin/java")
-        .append(" 
-Xmx").append(container.getResource().getMemory()).append("M")
+        .append(" -Xmx").append((int) (container.getResource().getMemory() * 
this.jvmMemoryXmxRatio) -
+            this.jvmMemoryOverheadMbs).append("M")
         .append(" ").append(JvmUtils.formatJvmArguments(this.containerJvmArgs))
         .append(" ").append(GobblinYarnTaskRunner.class.getName())
         .append(" 
--").append(GobblinClusterConfigurationKeys.APPLICATION_NAME_OPTION_NAME)
diff --git 
a/gobblin-yarn/src/test/java/org/apache/gobblin/yarn/GobblinYarnAppLauncherTest.java
 
b/gobblin-yarn/src/test/java/org/apache/gobblin/yarn/GobblinYarnAppLauncherTest.java
index f409f5f..c9ec435 100644
--- 
a/gobblin-yarn/src/test/java/org/apache/gobblin/yarn/GobblinYarnAppLauncherTest.java
+++ 
b/gobblin-yarn/src/test/java/org/apache/gobblin/yarn/GobblinYarnAppLauncherTest.java
@@ -182,6 +182,14 @@ public class GobblinYarnAppLauncherTest implements 
HelixMessageTestBase {
   }
 
   @Test
+  public void testBuildApplicationMasterCommand() {
+    String command = 
this.gobblinYarnAppLauncher.buildApplicationMasterCommand(64);
+
+    // 41 is from 64 * 0.8 - 10
+    Assert.assertTrue(command.contains("-Xmx41"));
+  }
+
+  @Test
   public void testCreateHelixCluster() throws Exception {
     // This is tested here instead of in HelixUtilsTest to avoid setting up 
yet another testing ZooKeeper server.
     HelixUtils.createGobblinHelixCluster(
diff --git 
a/gobblin-yarn/src/test/java/org/apache/gobblin/yarn/YarnServiceTest.java 
b/gobblin-yarn/src/test/java/org/apache/gobblin/yarn/YarnServiceTest.java
index 60aad14..29cd68d 100644
--- a/gobblin-yarn/src/test/java/org/apache/gobblin/yarn/YarnServiceTest.java
+++ b/gobblin-yarn/src/test/java/org/apache/gobblin/yarn/YarnServiceTest.java
@@ -250,6 +250,27 @@ public class YarnServiceTest {
     
Assert.assertTrue(yarnService.getReleasedContainerCache().getIfPresent(containerId1)
 == null);
   }
 
+  @Test(groups = {"gobblin.yarn", "disabledOnTravis"}, dependsOnMethods = 
"testReleasedContainerCache")
+  public void testBuildContainerCommand() throws Exception {
+    Config modifiedConfig = this.config
+        
.withValue(GobblinYarnConfigurationKeys.CONTAINER_JVM_MEMORY_OVERHEAD_MBS_KEY, 
ConfigValueFactory.fromAnyRef("10"))
+        
.withValue(GobblinYarnConfigurationKeys.CONTAINER_JVM_MEMORY_XMX_RATIO_KEY, 
ConfigValueFactory.fromAnyRef("0.8"));
+
+    TestYarnService yarnService =
+        new TestYarnService(modifiedConfig, "testApp2", "appId2",
+            this.clusterConf, FileSystem.getLocal(new Configuration()), 
this.eventBus);
+
+    ContainerId containerId = 
ContainerId.newInstance(ApplicationAttemptId.newInstance(ApplicationId.newInstance(1,
 0),
+        0), 0);
+    Resource resource = Resource.newInstance(2048, 1);
+    Container container = Container.newInstance(containerId, null, null, 
resource, null, null);
+
+    String command = yarnService.buildContainerCommand(container, 
"helixInstance1");
+
+    // 1628 is from 2048 * 0.8 - 10
+    Assert.assertTrue(command.contains("-Xmx1628"));
+  }
+
 
   private static class TestYarnService extends YarnService {
     public TestYarnService(Config config, String applicationName, String 
applicationId, YarnConfiguration yarnConfiguration,
diff --git a/gobblin-yarn/src/test/resources/GobblinYarnAppLauncherTest.conf 
b/gobblin-yarn/src/test/resources/GobblinYarnAppLauncherTest.conf
index d5d6bb3..89edb97 100644
--- a/gobblin-yarn/src/test/resources/GobblinYarnAppLauncherTest.conf
+++ b/gobblin-yarn/src/test/resources/GobblinYarnAppLauncherTest.conf
@@ -21,3 +21,6 @@ include "reference"
 gobblin.cluster.helix.cluster.name=GobblinYarnAppLauncherTest
 gobblin.yarn.app.name=GobblinYarnAppLauncherTest
 gobblin.yarn.work.dir=GobblinYarnAppLauncherTest
+
+gobblin.yarn.app.master.jvmMemoryOverheadMbs=10
+gobblin.yarn.app.master.jvmMemoryXmxRatio=0.8

Reply via email to