Spark 系列三

Spark 应用在进行问题排查或性能优化分析时,往往有固定的套路和方法,本文总结了过去处理Spark性能问题时的常用手段,希望能够帮到大家。

查看操作系统的资源使用情况

CPU使用情况

1
$ top

检查CPU使用率最常用的是 top 命令,除此之外还有很多其他的方法,具体可以参考 查看Linux CPU使用率的7种方法

内存

1
$ free -h

使用 free 命令可以看到服务器的内容总量以及使用的情况。

磁盘

1
2
$ df -lh
$ iostat -x 1s 10

磁盘主要包括空间和使用率的情况,使用率可以使用vmstatnetstat命令查看。

查看应用情况

查看进程内存

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

参考资料

  1. Spark作业性能优化
  2. Spark 任务执行排查慢的问题排查-2
  3. Spark job 异常排查-1
  4. analyzing java garbage collection logs debugging optimizing apache sparkTuning Java Garbage Collection for Apache Spark Applications
  5. Tuning Java Garbage Collection for Apache Spark Applications
  6. Troubleshooting Long GC Pauses
  7. Garbage First Garbage Collector Tuning
  8. Spark Configuration
  9. Spark Streaming Logging Configuration
  10. Analyzing Java Garbage Collection Logs for debugging and optimizing Apache Spark jobs

cocowool

A FULL STACK DREAMER!