引言
- 本文章为个人学习公司一个技术大佬写的 Spark 相关技术文档,个人手敲摘录的部分内容以及个人补充,涉密原因图片仅供参考(实际例子截图不能外传,且本地我没办法布集群,so...)
- 如果有错误欢迎指正,有问题可以一起探讨(由于本人非大数据岗,所以可探讨内容有限,文章内容参考即可)。
- 本文主要是关于 Spark 问题排查以及案例分析,后续会补充其他Spark 的相关问题。
1 问题排查步骤
- 若是运行中的任务,进入 SparkUI;若任务已结束,只能进入 HistoryServer
- 查看jobs 页面,找到执行异常的job。点击该 job 详细页面链接进一步查找异常(pending,skipped,failed)的 Stage:
- 若没有Stage 明显执行很慢,但是整体很慢,可能是有很多失败重试的 Stage
- 若 Stage 状态异常,可点击 detail 查看异常代码
- 点击 Stage 详细页面,查看 Task 统计信息:
- 若 GC 时间过长,考虑加大内存
- 点击 DAG 图,结合代码排查导致执行慢的算子
- 电机 Event Timeline,查看各类事件占用时间,如序列化和反序列化时间过长,可以考虑使用 kryo 提升序列化性能
- 进一步查看 Task 信息,找到执行慢或者异常的 Task:
- 若执行慢,排查是否发生了数据倾斜
- 若执行失败,点击右侧 details 查看失败的堆栈信息
2 异常案例分析
- 资源不足
- Stage 页面是否有等待的 Task,Executors 界面是分配足够的 Cores:
- 如果大量 Task 等待,Cores 很少,那就是资源不足
- 如果大量 Task 等待,Cores 充足,但是 Active Tasks 远小于 Cores,可能是 Driver 调度性能不足,也可能是每个 Task 执行时间太短,秒级别返回,来不及发新的 Task
- 大量失败重试
- Stage 页面有大量的retry,一定要先进行错误定位,即使最后运行成功,也会浪费大量计算资源
- 最常见的失败原因就是 shuffle,因此需要尽量避免 shuffle 或者优化 shuffle
- 节点异常
- 执行慢的 Stage 详细页面,按运行顺序排序,看执行慢的 Task 是否集中在同一个 IP
- 如果是,可以找计算集群运维排查机器情况
- 代码段卡住
- Executors页面找到有执行的 Task的 Executors,点击 Tread Dump,查看堆栈信息进一步排查
- 数据倾斜
- 在执行过程中,会遇到执行时间很长的情况,其中有一个可能性就是数据倾斜
- 判断倾斜的标准之一:Stage 菜单中,对应 stage 的 description 链接里的 metrics 表格
- 可以查看"shuffle Read Size"或者 input size 那一栏中,各个 Task 读取数据量的最值,中位数等并不均匀,如果是更加极端的数据倾斜,"Duration"一栏的最大执行时间也会很长
- 数据倾斜的另一个现象就是在 application 运行中,Executors 菜单里active 状态的 executors 数量只有几个,大部分的 executors 都是 dead 状态,这是因为开启了 Dynamic Allocation 特性,executors 只要空闲(idle)超过 60s 就会被资源回收
- 此时也可以看到 stages 界面正在执行的 stage 只有个别 Task 在 running
- 这样的 stage 电机 Description 列的蓝色链接进去后,下方的 Task 表格中,处在 running 状态的个别 task 说读取的数据量(shuffle read 或者 input 列)远比其他的 task 大
- 数据倾斜有时也会伴随个别 Task 所属的 executors 内存溢出的现象(查看具体的 failure reason)
- 小文件过多
- 表现之一:各Task 读取的数据量远小于一个 hdfs block 大小:
- 有时小文件多造成的 Task 数量过多,导致 driver full gc 从而导致 Spark ui 网页打不开从而看不到 stage 情况,这是因为 driver 内存有限且负责 Spark ui 的 metrics 信息状态维护(需要去 hadoop 可视化界面)
- 小文件过多也可能导致内存溢出,因为用于读取每个文件的 read 对象,Spark 都会在内存中生成一个 1M 大小的缓冲区
- 笛卡尔积/数据量膨胀
- stage 菜单中,对应stage 的 description 链接进去后,下方有个各executors 对应 Task 运行情况的表格
- 如果输入的数据量(容量与 records 数)远比输出数据量小,再看 DAG图里有涉及到 join 的操作,那说明左右表 join 的字段可能有重复值,发生了笛卡尔积/数据量膨胀
- 另一个可能:对应 stage 的 description 链接里的 metrics 表格中,如果 shuffle write 的记录数远大于 shuffle read 的记录数,也说明 join 的字段值可能有重复,交错关联导致数据量膨胀了
- OOM
- 如果数据量很大,数据倾斜,并发度不合理,代码逻辑不合理等原因,都会导致 derive 或者 executors 的内存不够出现 oom 错误
- "java.1ang.OutOFMemoryError:Java heap space"
- Yarn 队列资源不足
- 当 application 跑的比较慢的时候,除了上面所述的原因外,还可能是同一个 yarn 队列中正在执行的 application 太多,或者是某个 application 不够优化占据过多资源堵塞了其他的 application
- 现象 1:如果自己队列显示为黄色,或者已使用的资源中,内存或者 cpu 核数其中一项已经达到最小资源阈值,或者最小资源非常小,说明自己队列中当前时刻的资源不足
- 现象 2:driver 中的stderr 等日志中有如下的未申请到资源的内容
- "Initial job has not accepted any resources"
- 现象 3:如果 Spark ui 的 job 或者 stage 界面中,正在运行的 job 或者 stage 只有少数的 Task 在长时间 running,并且进入该 stage 的 description 链接后,观察 metrics 表格并未发现有某个 Task 数据量巨大的数据倾斜现象,说明暂时申请不到更多的 executors 来更高并发的运行多个 task
- 现象 4:如果发现任务本身长时间并没有实际执行起来,在 application 的详情界面中看到下图中的 node 列没有指定 IP 或域名的现象,说明此时没有启动 application master,大概率也是 yarn 队列没资源了