Spark 应用在进行问题排查或性能优化分析时,往往有固定的套路和方法,本文总结了过去处理Spark性能问题时的常用手段,希望能够帮到大家。
查看操作系统的资源使用情况
CPU使用情况
1 | $ top |
检查CPU使用率最常用的是 top
命令,除此之外还有很多其他的方法,具体可以参考 查看Linux CPU使用率的7种方法
内存
1 | $ free -h |
使用 free 命令可以看到服务器的内容总量以及使用的情况。
磁盘
1 | $ df -lh |
磁盘主要包括空间和使用率的情况,使用率可以使用vmstat
、netstat
命令查看。
查看应用情况
查看进程内存
1 | $ jmap -heap processId |
因为Spark集中使用内存的特性,为Spark程序分配超过100G的堆空间是很常见的事情,这种情况在传统的Java应用中却不常见。
查看GC情况
1 | $ jstat -gcutil processId 1s 60 |
查看HeapDump
使用-XX:HeapDumpOnOutOfMemoryError
可以在发生OOM的时候自动生成DUMP文件。
RDD使用的空间越小,Heap使用的空间就越大,更大的Heap空间带来更高的内存使用效率。
打开Executor的GC日志
1 | --conf spark.executor.extraJavaOptions="-XX:+PrintFlagsFinal -XX:PrintReferenceGC -verbose:gc -XX:+PrintGCDetails -XX:PrintGCTimeStamps -XX:PrintAdaptiveSizePolicy -XX:+UnlockDiagnosticVMOptions -XX:G1SummarizeConcMark" |
打开Driver的GC日志
1 | --conf spark.driver.extraJavaOptions="-XX:+PrintFlagsFinal -XX:PrintReferenceGC -verbose:gc -XX:+PrintGCDetails -XX:PrintGCTimeStamps -XX:PrintAdaptiveSizePolicy -XX:+UnlockDiagnosticVMOptions -XX:G1SummarizeConcMark" |
- 是否有内存泄漏。Memory Leak
- 使用工具查看GC的统计数据
当Spark GC频繁发生或者持续很长时间的时候,说明内存没有被有效使用,可以通过强制清理缓存的RDD来提高内存使用效率。
优化建议
- 降低
InitiatingHeapOccupancyPercent
的值,默认为45. - 增加
ConcGCThreads
的值。 - 增加
G1HeapRegionSize
的值,避免创建过大的Heap区域。如果确实程序需要很多的大对象,就需要仔细的调整-XX:G1HeapWastePercent -XX:G1MixedGCLiveThresholdPercent
参数来避免这种情况。 - 如果想减少STW的数量,可以减小
G1RSetUpdatingPauseTimePercent
参数,同时增加G1ConcRefinementThreads
- 对于长时间运行的程序,可以使用
AlwaysPreTouch
参数,这样JVM在启动的时候就会向OS申请必须的内存,从而避免动态的调整。
参考配置
-XX:+UseG1GC -XX:+PrintFlagsFinal -XX:+PrintReferenceGC -verbose:gc -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintAdaptiveSizePolicy -XX:+UnlockDiagnosticVMOptions -XX:+G1SummarizeConcMark -Xms88g -Xmx88g -XX:InitiatingHeapOccupancyPercent=35 -XX:ConcGCThread=20
相关参数
- spark.core.connection.ack.wait.timeout 避免因网络或GC造成任务丢失
- spark.speculation true 开启推测机制,避免某台慢造成影响
- spark.speculation.interval 100 单位毫秒
- spark.speculation.quantile 0.75
- spark.speculation.multiplier 1.5 比其他慢1.5倍时启动推测
- spark.shuffle.io.numConnectionsPerPeer
- spark.storage.memoryFraction 控制cached RDD所占的空间比例
以pid分割spark日志
生产集群上Spark以脚本的方式启动,每个Worker上会启动三个Executor,脚本文件中gc的日志文件写了一个固定目录,结果发现gc日志会产生相互覆盖,对于排查生产问题不利,因此想要每个单独的Executor生产自己的gc日志文件。
查看官方文档,知道可以使用spark.executor.extraJavaOptions
指定gc的目录,对于如何根据分隔日志,官方的描述感觉并不清晰。
A string of extra JVM options to pass to executors. For instance, GC settings or other logging. Note that it is illegal to set Spark properties or maximum heap size (-Xmx) settings with this option. Spark properties should be set using a SparkConf object or the spark-defaults.conf file used with the spark-submit script. Maximum heap size settings can be set with spark.executor.memory. The following symbols, if present will be interpolated: will be replaced by application ID and will be replaced by executor ID. For example, to enable verbose gc logging to a file named for the executor ID of the app in /tmp, pass a ‘value’ of: -verbose:gc -Xloggc:/tmp/-.gc
%p
参考资料
- Spark作业性能优化
- Spark 任务执行排查慢的问题排查-2
- Spark job 异常排查-1
- analyzing java garbage collection logs debugging optimizing apache sparkTuning Java Garbage Collection for Apache Spark Applications
- Tuning Java Garbage Collection for Apache Spark Applications
- Troubleshooting Long GC Pauses
- Garbage First Garbage Collector Tuning
- Spark Configuration
- Spark Streaming Logging Configuration
- Analyzing Java Garbage Collection Logs for debugging and optimizing Apache Spark jobs