最近在玩 Spark ,它是个基于内存的分布式计算框架,用起来还是挺方便的,而且相当适合需要迭代计算的算法,比如PageRank和机器学习的算法。Spark的社区相当活跃,每天都有很多user提问,每天的commit数也是超过1000的。
以前Spark利用mesos集群或者用自己启动的集群来进行分布式计算。由于国内很多公司只维护了hadoop集群,我没能看到Spark有投入到生产中(要维护多一个mesos集群成本可是很高的)。然而,在0.6的版本中加入了 on Yarn 模块。这使得很多部署了hadoop集群的公司(升级成支持Yarn的hadoop)可以轻易的使用Spark了。
要好好玩Spark还是需要一点时间的,因为现在的版本还是有不少bug和todo的。最近玩的时候还是遇到了个比较让人头大的问题的,当我迭代调用collect方法的时候,会出现一个让人比较头大的问题:
- Master无缘无故就跑的很慢
- 使得akka超时
- Yarn的ResourcesManager告诉我Master用的内存超出预算
出现这个问题之后,我还是真不知道怎么定位原因,现在解决了之后,感觉自己的编程经验还真是太少了。
print GC
首先,我PrintGC的信息,在启动参数中加入下面的参数:
- -verbose:gc: 输出GC信息
- -XX:+PrintGCTimeStamps:输出GC时间
- -XX:+PrintGCDetails:输出GC详细信息,比如新生代GC情况,永久代GC情况,内存的GC汇总等
在这里,我发现Master崩溃前会不断Full GC,并且Full GC后,老年代的内存用量没有降下来,这只可能是用的内存真的需要这么多(给了10G的内存还崩溃真说不过去),或者内存泄露。
dump 内存
这里说的dump就是抽取jvm内存使用状况的快照。启动参数里面还是有不少关于dump的参数的:
- -XX:-HeapDumpOnOutOfMemoryError:在OOM时,输出一个dump文件,记录当时的内存快照
- -XX:HeapDumpPath=/tmp/dump.hprof:把dump信息输出到/tmp/dump.hprof中
dump文件的大小通常是jvm占用内存的大小,所以文件可能会很大。
分析dump文件
这是最后的步骤,也是很耗时的步骤了,dump文件是结构化得文件,需要用分析工具才能分析。
- jhat:dump文件少于1G的时候可以用这个,它会起一个web服务,用于查看dump信息。
- HeapAnalyzer:直接分析dump并展示的客户端。
- mat:同样是展示dump的客户端,神器
使用 jhat 和 HeapAnalyzer 都需要有一台内存大于dump文件大小2倍的机器,HeapAnalyzer还需要能显示出来的(桌面操作系统),这下就悲剧了,这样的机器相当难找。
这时可以用强大的mat,mat分析了展示和分析模块,可以用一个脚本先对dump文件分析并产生一堆索引文件(用服务器搞),然后再用mat的桌面应用打开这些文件,4G内存的机器分析8g的dump完全没压力的。
点击这里看教程
最后
用mat找到这个内存泄露的地方了,提个issue,然后就fork and pull request去。
评论
发表评论