在Docker中运行Spark时抛出java.lang.OutOfMemoryError

我试图在Docker中运行一个Spark实例,并经常得到这个exception:

16/10/30 23:20:26 ERROR SparkUncaughtExceptionHandler: Uncaught exception in thread Thread[Executor task launch worker-1,5,main] java.lang.OutOfMemoryError: unable to create new native thread 

我正在使用这个Docker镜像https://github.com/sequenceiq/docker-spark 。

我的限制在容器内似乎没问题:

 bash-4.1# ulimit -a core file size (blocks, -c) unlimited data seg size (kbytes, -d) unlimited scheduling priority (-e) 0 file size (blocks, -f) unlimited pending signals (-i) 29747 max locked memory (kbytes, -l) 64 max memory size (kbytes, -m) unlimited open files (-n) 1048576 pipe size (512 bytes, -p) 8 POSIX message queues (bytes, -q) 819200 real-time priority (-r) 0 stack size (kbytes, -s) 8192 cpu time (seconds, -t) unlimited max user processes (-u) 1048576 virtual memory (kbytes, -v) unlimited file locks (-x) unlimited 

他们也看起来不错,在主机外面的容器:

 kane@thinkpad ~> ulimit -a core file size (blocks, -c) unlimited data seg size (kbytes, -d) unlimited scheduling priority (-e) 0 file size (blocks, -f) unlimited pending signals (-i) 29747 max locked memory (kbytes, -l) 64 max memory size (kbytes, -m) unlimited open files (-n) 1024 pipe size (512 bytes, -p) 8 POSIX message queues (bytes, -q) 819200 real-time priority (-r) 0 stack size (kbytes, -s) 8192 cpu time (seconds, -t) unlimited max user processes (-u) 29747 virtual memory (kbytes, -v) unlimited file locks (-x) unlimited 

我的谷歌search告诉我,systemd可以限制任务,并导致这个问题,但我已经把我的任务限制设置为无穷大:

 kane@thinkpad ~> grep TasksMax /usr/lib/systemd/system/docker.service 20:TasksMax=infinity kane@thinkpad ~> systemctl status docker ● docker.service - Docker Application Container Engine Loaded: loaded (/usr/lib/systemd/system/docker.service; enabled; vendor preset: disabled) Active: active (running) since Mon 2016-10-31 08:22:39 AWST; 3h 14min ago Docs: http://docs.docker.com Main PID: 1107 (docker-current) Tasks: 56 Memory: 34.9M CPU: 30.292s 

有任何想法吗? 我的Spark代码只是从一个Kafka实例(运行在一个单独的Docker容器中)中读取数据,然后做一个基本的map / reduce操作。 没有什么花哨。

错误说明你不能创build更多的本地线程,因为你没有足够的内存。 这并不一定意味着你达到了限制,但你没有足够的内存来创build更多的线程。

在JVM中创build线程的内存大小由-XSS标志控制,如果我没有记错的话,默认为1024K。 如果你没有太多的recursion调用,你可以尝试减lessXSS标志,并能够用相同的可用内存量创build更多的线程。 如果XSS太小,您将遇到StackOverFlowError

docker-spark图片使用包含HDFS和Yarn服务的hadoop-docker镜像您的容器可能会为您的JVM堆大小(hdfs,yarns)分配太多内存,因此没有足够的内存来分配新线程。

希望它会有所帮助