了解Spark容器故障

时间:2016-08-19 11:53:22

标签: java amazon-web-services apache-spark

我有一个在AWS EMR上运行的 Spark 作业。它经常在几个步骤后失败,并提供错误消息,如:

   Try This

         RequestQueue queue = Volley.newRequestQueue(this); 
       final String url = "http://httpbin.org/get?param1=hello";

    //prepare the Request
   JsonObjectRequest getRequest = new JsonObjectRequest(Request.Method.GET, url, null,
new Response.Listener<JSONObject>() 
{
    @Override
    public void onResponse(JSONObject response) {   
  JSONArray responserecentbooks = response.getJSONArray("arrayname");
                for (int i = 0; i < responserecentbooks.length(); i++) {
                    JSONObject person = (JSONObject) responserecentbooks.get(i);
                    String bookid = person.getString("element");
                   //store values in Arraylist 
                    try {

                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        Log.d("Response", response.toString());
    }
}, 
new Response.ErrorListener() 
{
     @Override
     public void onErrorResponse(VolleyError error) {            
        Log.d("Error.Response", response);
   }
}
);

 // add it to the RequestQueue   
 queue.add(getRequest);

据我所知,这似乎是一个OOM错误。在日志中更早看,我可以看到:

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

我的问题:

  1. 这是一个OOM吗?
  2. 为什么过度分配(?)和退出之间有10分钟的差距?
  3. 我的工作中是否需要更多的执行者?或者我的某个地方有不正确的参与者?

2 个答案:

答案 0 :(得分:4)

你的第一个问题的答案几乎肯定是#34;是&#34;。我猜测如果你看一下纱线节点管理器日志,你会看到一些超出物理内存和#34; - 这些基本上是YOM的YARN语言。

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

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

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

2)您可能处于数据非常偏斜的情况,在这种情况下,您可以通过重新分区数据或重新思考数据的分区方式来解决问题。

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

一般情况下,我建议您查看群集在Ganglia中的使用情况。如果Ganglia只显示一些工作人员正在做任何事情,那么你最有可能在方案2中。如果所有工作人员都被使用而你只是耗尽所有可用内存,那么应该考虑方案3。

我希望这会有所帮助。

答案 1 :(得分:1)

<是> OOM,是的,但我们在这里谈论的是什么样的记忆?堆,堆外?如果您正在使用Spark 1.4或之前的版本,我敢打赌,这个错误发生在大量数据中,并且是由Netty内存泄漏(在shuffle期间分配的堆外内存)引起的。

如果它真的与堆内存有关,那么你应该能够在日志中找到关于GC的东西。否则,这几乎肯定是堆外内存。在发生故障之前,您可以在其中一个从服务器上执行堆转储,以确定哪种类型的内存超出了分配给容器的数量。

另外,你的容器看起来很大(50演出的音乐记忆?)。听起来像是你在一个容器上做了很多工作,所以拥有更小的容器会更有意义,但是其中很多都完成了较小的工作?以下是当前接受的答案中未提出的可能的解决方法:

  • 如果您的群集有足够的内存,则可以增加固定数量核心的容器数量。每个容器将获得相同数量的内存,因此每个容器上具有较少并发任务的更多容器意味着以相同速度完成任务的更多总体内存(唯一的缺点是变得更昂贵的广播)。这可以通过spark.executor.instancesspark.executor.cores进行控制。作业的核心总数是两者的乘积。
  • 只需使用更多的分区。拥有一些大的分区是非常低效的,拥有许多小分区会更好(但不能太小,否则每个任务的开销会比任务本身的执行更大)。
  • 如果您可以证明它是由于堆外内存过多,您可以使用spark.shuffle.io.preferDirectBufs=false禁用堆外内存使用。但是,执行此操作会导致您的作业在随机播放过程中花费更多时间在GC中,因此您可能还需要增加堆大小。如果你在Spark 1.4下,你也可以升级到修复Netty内存泄漏的更高版本(在迁移期间要小心,因为Spark 1.6.1引入了一些其他的堆内存问题。请参阅https://issues.apache.org/jira/browse/SPARK-14560)< / LI>