《Spark 常见问题排查》
本文汇总 Spark(含 Structured Streaming / Spark Streaming)使用过程中的常见报错与排查思路。
1 Task not serializable
在 driver 上初始化了一个变量 x,但在 executor 中使用它,Spark 需要将这个变量序列化后传给 executor;如果对象不可序列化,就会报此错误。
排查与解决:
- 将不可序列化的对象定义在闭包内。
- 将所调用的方法改为函数,在高阶函数中使用。
- 给无法序列化的类加上
java.io.Serializable接口。 - 通过
jars注册序列化类。
2 日志写入无权限(Permission denied)
报错示例:
java.io.FileNotFoundException: /home/work/services/spark-env/logs/xxx.log (Permission denied)
原因:文件权限导致程序无法写入日志。
解决:
chmod o+w /home/work/services/spark-env/logs/
chmod o+w /home/work/services/spark-env/logs/xxx.log
3 Offsets out of range with no configured reset policy
报错示例:
org.apache.kafka.clients.consumer.OffsetOutOfRangeException: Offsets out of range
with no configured reset policy for partitions: {...}
原因:group.id 上次提交的 offset 已超出 Kafka 保留范围(数据被删除),新程序沿用旧 group 消费导致 offset 越界。
解决:换一个新的 group.id。
相关 issue:https://issues.apache.org/jira/browse/SPARK-19680
4 requirement failed: Failed to get records
报错示例:
java.lang.IllegalArgumentException: requirement failed: Failed to get records for xxx
after polling for 30000
at org.apache.spark.streaming.kafka010.CachedKafkaConsumer.get(CachedKafkaConsumer.scala:72)
原因:同上,程序从上次结束的 offset 继续消费,但该位置的数据已被删除。
解决:更换 group.id 后重启程序。
5 com.alibaba.fastjson NullPointerException
原因:JSONObject 中没有某个 key,直接调用 getInteger 等 getter 会抛出空指针。
解决:调用 getter 之前先 containsKey 判断。
if (jsonObj.containsKey("key")) {
val v = jsonObj.getInteger("key")
}
6 程序处理时间过长
从 Web UI 选择【Streaming】→【Completed Batches】→【Batch Time】,选择一个完成的 batch,即可看到 Output Op Duration。
DStream 上常见 5 种 Output Operation:
print()saveAsTextFiles(prefix, [suffix])saveAsObjectFiles(prefix, [suffix])saveAsHadoopFiles(prefix, [suffix])foreachRDD(func)
Output Op Duration 与 Job Duration 的时间差,就是 Output Operation 在 driver 端代码的运行时间,可用于定位耗时集中在 driver 还是 executor。
7 调整日志级别
将 log4j.properties.template 复制为 log4j.properties 并修改根级别,减少干扰日志:
cp ${SPARK_HOME}/conf/log4j.properties.template ${SPARK_HOME}/conf/log4j.properties
vi ${SPARK_HOME}/conf/log4j.properties
#log4j.rootCategory=INFO, console
log4j.rootCategory=WARN, console
8 历史告警 EventCounter is deprecated
WARNING: org.apache.hadoop.metrics.jvm.EventCounter is deprecated.
Please use org.apache.hadoop.log.metrics.EventCounter in all the log4j.properties files.
将 log4j.properties 中的 org.apache.hadoop.metrics.jvm.EventCounter 替换为 org.apache.hadoop.log.metrics.EventCounter 即可消除告警。