Spark 运行状态监控与优化
当我们调试 spark 程序或者排查任务运行状态的时候,除了看 spark 提供的原生日志以外,spark 还为我们提供了很好的监控工具 Monitor,具体的参数详情可以参考Monitoring and Instrumentation。我们本章通过讲解一个 spark 进行资源优化和并发调整的例子来演示如何用好 Monitor 工具。
1、测试环境
![](https://static001.geekbang.org/infoq/70/70a05347881e674d6f7b1e010021b287.png)
队列总资源
2、任务测试
(1)任务配置-1
![](https://static001.geekbang.org/infoq/da/da782d7f5b9bb7320ba6abe4da8122a7.png)
运行情况
![](https://static001.geekbang.org/infoq/24/2454f2804ffac9c91d47d4675d1a6082.png)
监控内容:上图是 SPARK 任务监控的几个方面,Jobs 是一个 Application 包含的 Job 详情,一个 Application 可能包含一个或多个 Job;Stages 是一个 Job 包含的 Stage 详情,一个 Job 会被划分为一个或多个 Stage;Environment 包含了 Application 提交的配置信息;Executor 包含了运行的 Executor 数以及 Executor 中的 Task 信息;SQL 可以查看具体的任务执行详情。
![](https://static001.geekbang.org/infoq/b0/b0da148d127787159b04feeb06d04aad.png)
Executor 分析:在 Executor 中,我们看到如上图所示的详情,从 Summary 的统计的中,我们可以看到整个任务启动的 Executor 有 24 个,我们也可以推算出来,24 个 Executor 大约 200G,加上其他的一些内存耗费,基本上用完了整个队列 240G 的内存资源。
![](https://static001.geekbang.org/infoq/df/df98eec990129ce4d56fa32881dc07f0.png)
Jobs 分析:通过 Jobs 模块可以查看 Application 的每个 Job 的运行时间。
(2)任务配置-2
我们修改配置,将内存减为原来的一半,再继续跑一下测试。
![](https://static001.geekbang.org/infoq/4b/4bd431e2f5f6055b7a2594659c7feda1.png)
运行情况
![](https://static001.geekbang.org/infoq/7d/7dc7c6384afb38470ebb201243a4df79.png)
Executor 分析:在 Executor 中,我们看到如上图所示的详情,从 Summary 的统计的中,我们可以看到整个任务启动的 Executor 有 30 个了,我们同样也可以推算出来,30 个 Executor 大约 120G 内存,加上其他的一些内存耗费,可能整个队列还剩一百多的内存剩余,但是为什么不继续开 Executor 了呢,因为 30 个 Executor 已经用完了 60 个 core,我们的整个队列资源上限就是 60 个 core,所以相当于内核限制了并发上限。
![](https://static001.geekbang.org/infoq/a1/a14de2d71cb444ad6d7a1acd7c7e9697.png)
Jobs 分析:这是通过 Jobs 看到的具体 Job 运行信息,在这里,我们惊奇的发现,虽然并发提高了一点点,但是具体的 Job 运行时间并没有缩短,这就有点违背常理。于是我有调整以下配置,将 Executor 内存可劲儿调大到 16G。
(3)任务配置-3
![](https://static001.geekbang.org/infoq/6b/6b5275e0f7d432c204322ace507907ab.png)
运行情况
![](https://static001.geekbang.org/infoq/f6/f6c4f6abd0dff2999a10d120942d4d76.png)
Executor 分析:通过上面我们看到,Executor 总数大大缩减了只有 13 个,并发性能大大减少,那再看一下 Job 运行时间是否有改变。
![](https://static001.geekbang.org/infoq/12/12d0d155fd7622571047dd6b237a9deb.png)
Jobs 分析:可以看到,其中 Job1 的运行时间确实增为原来的 2 倍左右,说明内存和并发对性能还是有影响的。但是,Job2 和 Job3 的时间似乎并没有改变,而且可以发现,三个配置的 Job2/3 的运行时间都没什么改变,这是什么原因呢。
于是通过 Executor 模块查看 Executor 的具体任务运行详情,可以看到 Executor18 和 19 的运行任务数远超过其他的 Executor,这就说明在任务分配的时候,出现了任务分配不均的问题。根据经验,我们自然而然的想到数据本地性的问题,数据本地性就是 task 在执行前都会获取数据的分区信息进行分配,总是会优先将其分配到它要计算的数据所在节点,尽可能的减少网络传输。所以,我又进行了数据本地性的验证。
![](https://static001.geekbang.org/infoq/e9/e95e6aad245449fca2ac2bdd18607faa.png)
(4)数据本地性验证
我拿 Job3 为例,来具体看一下任务运行情况。,
![](https://static001.geekbang.org/infoq/0d/0d641a5705a7c02bf85bebf837d7e067.png)
![](https://static001.geekbang.org/infoq/55/551d3fabb1675e6f3f8ed273dec38c52.png)
Executor 分析:通过上面可以分析,对于 Job3 的 Stage9,只有两个 Executor 来运行,而其他的二十几个 Executor 在这个 Stage 运行的时候处于空闲状态。
locality 调节:
我于是将“数据本地化等待时长 ” spark.locality.wait 设置为 0,也就是基本消除数据本地化任务分配策略,然后运行看看效果。
![](https://static001.geekbang.org/infoq/94/943c605ee2a4341c78e8fda2fd0fbf68.png)
通过上面对信息,可以看到调整了数据本地化策略后,Job2 和 Job3 的运行时长大幅缩短,我们进一步看更详细的信息。
![](https://static001.geekbang.org/infoq/fc/fcd261959f303fc94469cc68a1ab9338.png)
通过上面 Executor 信息可以观察到,任务被平均分配到了各个 Executor,达到了充分利用 Executor 的效果,因此运行时间大幅缩短。所以,如果遇到这种情况,我们可以通过调整数据本地性参数来优化任务执行。
![](https://static001.geekbang.org/infoq/63/639056ab08f58b5416ff2d4979eb978a.png)
另外,我们还注意到一个问题,就是 Storage Memory 的监控显示,内存利用其实并不充分,内存大部分都在闲置,所以我们可以将 Executor 内存再继续调小。
![](https://static001.geekbang.org/infoq/9f/9f3a06de59189c67a5e3d6b3f92ec414.png)
继续调小内存,发现依然可以运行,但是开始出现 gc 问题,所以说适可而止,适当评估。
总结
上面我们相当于借助 SPARK Monitor 来对任务进行一系列的分析,然后对内存、并发等问题进行排查并优化。如果 spark 任务除了问题,多分析分析吧~
版权声明: 本文为 InfoQ 作者【小舰】的原创文章。
原文链接:【http://xie.infoq.cn/article/ad091ae20d5846b8960f96fbd】。文章转载请联系作者。
评论