了解Spark容器故障

eth*_*nny 2 java amazon-web-services apache-spark

我有一个在AWS EMR上运行的Spark作业。几个步骤后,它通常会失败,并显示以下错误消息:

2016-08-18 23:29:50,167 INFO org.apache.hadoop.yarn.server.nodemanager.containermanager.monitor.ContainersMonitorImpl (Container Monitor): Memory usage of ProcessTree 7031 for container-id container_: 48.6 GB of 52 GB physical memory used; 52.6 GB of 260 GB virtual memory used  
2016-08-18 23:29:53,191 INFO org.apache.hadoop.yarn.server.nodemanager.containermanager.monitor.ContainersMonitorImpl (Container Monitor): Memory usage of ProcessTree 7031 for container-id container_: 1.2 MB of 52 GB physical memory used; 110.4 MB of 260 GB virtual memory used   
2016-08-18 23:29:56,208 INFO org.apache.hadoop.yarn.server.nodemanager.containermanager.monitor.ContainersMonitorImpl (Container Monitor): Memory usage of ProcessTree 7031 for container-id container_: 1.2 MB of 52 GB physical memory used; 110.4 MB of 260 GB virtual memory used    
2016-08-18 23:29:56,385 WARN org.apache.hadoop.yarn.server.nodemanager.DefaultContainerExecutor (ContainersLauncher #0): Exit code from container container_ is : 52   
2016-08-18 23:29:56,387 WARN org.apache.hadoop.yarn.server.nodemanager.DefaultContainerExecutor (ContainersLauncher #0): Exception from container-launch with container ID: container_ and exit code: 52   
org.apache.hadoop.util.Shell$ExitCodeException: 
  at org.apache.hadoop.util.Shell.runCommand(Shell.java:505)
  at org.apache.hadoop.util.Shell.run(Shell.java:418)
  at org.apache.hadoop.util.Shell$ShellCommandExecutor.execute(Shell.java:650)
  at org.apache.hadoop.yarn.server.nodemanager.DefaultContainerExecutor.launchContainer(DefaultContainerExecutor.java:200)
  at org.apache.hadoop.yarn.server.nodemanager.containermanager.launcher.ContainerLaunch.call(ContainerLaunch.java:300)
  at org.apache.hadoop.yarn.server.nodemanager.containermanager.launcher.ContainerLaunch.call(ContainerLaunch.java:81)
  at java.util.concurrent.FutureTask.run(FutureTask.java:266)
  at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
  at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
  at java.lang.Thread.run(Thread.java:745)
2016-08-18 23:29:56,393 INFO org.apache.hadoop.yarn.server.nodemanager.ContainerExecutor (ContainersLauncher #0): 
2016-08-18 23:29:56,455 WARN org.apache.hadoop.yarn.server.nodemanager.containermanager.launcher.ContainerLaunch (ContainersLauncher #0): Container exited with a non-zero exit code 52
Run Code Online (Sandbox Code Playgroud)

从我可以发现,这似乎是一个OOM错误。在日志中查看较早时,我可以看到:

2016-08-18 23:19:00,462 INFO org.apache.hadoop.yarn.server.nodemanager.containermanager.monitor.ContainersMonitorImpl (Container Monitor): Memory usage of ProcessTree 7031 for container-id container_: 53.6 GB of 52 GB physical memory used; 104.4 GB of 260 GB virtual memory used   
2016-08-18 23:19:03,480 INFO org.apache.hadoop.yarn.server.nodemanager.containermanager.monitor.ContainersMonitorImpl (Container Monitor): Memory usage of ProcessTree 7031 for container-id container_: 53.9 GB of 52 GB physical memory used; 104.4 GB of 260 GB virtual memory used    
2016-08-18 23:19:06,498 INFO org.apache.hadoop.yarn.server.nodemanager.containermanager.monitor.ContainersMonitorImpl (Container Monitor): Memory usage of ProcessTree 7031 for container-id container_: 53.9 GB of 52 GB physical memory used; 104.4 GB of 260 GB virtual memory used
2016-08-18 23:19:09,516 INFO org.apache.hadoop.yarn.server.nodemanager.containermanager.monitor.ContainersMonitorImpl (Container Monitor): Memory usage of ProcessTree 7031 for container-id container_: 53.8 GB of 52 GB physical memory used; 104.4 GB of 260 GB virtual memory used
Run Code Online (Sandbox Code Playgroud)

我的问题:

  1. 这是OOM吗?
  2. 为什么超额分配(?)与出口之间有10分钟的间隔?
  3. 我在工作中需要更多的执行者,还是某个地方的参数不正确?

Gle*_*olt 5

您第一个问题的答案几乎肯定是“是”。我猜想,如果您查看yarn nodemanager日志,将会看到许多“超出物理内存范围”错误,这基本上是OOM的YARN语言。

至于问题2,执行者当然会在遇到OOM时死亡,但是通常您的工作不会立即被杀死。YARN必须对突然死亡的执行者具有弹性,因此它将简单地尝试再次从其他执行者上重新执行失败的执行者的任务。只有当几个执行者死亡时,它才会关闭您的工作。

最后,OOM可能由于多种原因而发生,并且解决方案取决于原因,因此您必须进行一些挖掘:)以下是您可能要研究的几个典型原因:

1)如果您尚未这样做,则可能需要增加spark.memoryOverhead。默认设置取决于可用内存,但是我发现它通常太低,因此增加它通常会有所帮助。但是,如果发现需要增加到memoryOverhead可用内存的1/3以上,则可能应该寻找其他解决方案。

2)您可能处于数据非常不对称的情况下,在这种情况下,您可以通过重新分区数据或重新考虑如何首先分区数据来解决问题。

3)您的集群可能根本无法满足您的需求,或者您可能运行的实例类型不适合您的工作。更改为具有更多内存的实例类型可能会解决您的问题。

通常,我建议您研究一下Ganglia中集群的使用情况。如果Ganglia仅显示几个工作人员在做任何事情,则您很可能在方案2中。如果所有工人都被使用,而您仅用尽所有可用内存,则应考虑方案3。

我希望这有帮助。