近几年Spark Native加速技术高速发展、技术栈日益丰富,各大厂商积极迭代支持,目前基本可以达到生产可用级别。技术栈大致分为以下几种:
Photon属于Databricks的闭源项目,这里笔者不过多介绍。Gluten + Velox/ClickHouse是Intel、Kyligence 、Meta(FaceBook)开源维护,Star(1.2K),Contributors(156),属于apache孵化项目。datafusion-comet是苹果开源维护,Star(844),Contributors(54),属于apache顶级项目。Blaze是快手开源维护、Star(1.3k),Contributors(22)。spark-rapids属于英伟达开源维护,Star(832),Contributors(76)。综合考虑了开发语言、社区状态,我们采用Gluten技术栈以提高客户现场环境集群资源的利用率。
现场人员反馈新上线业务SparkSQL使能Gluten环境中的作业性能很差,耗时甚至比原生Spark更长。经过反复沟通确认只有新上线SQL中的一个SQL有这种问题,虽然耗时比较长,但计算结果是准确的。查看该SQL对应的SparkUI发现存在大量失败重试的Task,如下图所示:
大量Task失败重试,整个SQL作业的耗时较长也就容易理解了!接下来就需要深究Task失败的具体原因。
通过上图SparkUI发现除了大量Task失败,还发现另外一个不正常的现象:就是存在多个Dead的Executor。
SparkDriver生成执行计划发给SparkExecutor执行实际的Task,正常情况下Executor不会无缘无故地退出。首先怀疑是OOM或者心跳超时导致的,但是查看Dead Executor日志,如下图所示:
并没有发现out of memory或者其他exception,也没有发现心跳超时Driver主动停止Executor的记录:Driver commanded a shutdown。从日志来看,executor正在执行shuffle操作,进程突然就退出了。查看操作系统日志dmesg -T|grep kill,也未发现杀掉进程的记录。没办法,只能继续查看Dead Executor所属container对应的NodeManager日志,如下图所示:
从日志来看,没有ERROR级别记录。但是WARN级别日志可以看到ExitCodeException,也就看出了端倪:container进程退出了,Exit code: 134。查看标准输出stdout日志,如下图所示:
果然stdout日志记录了因为fatal error导致JVM crash的原因,看样子跟netty有关。本来可以继续打开core dump排查根因,如下:
-XX:+CreateCoredumpOnCrash -XX:HeapDumpPath=/path/to/heapdump.hprof
但是,查看Netty社区相关issue描述类似异常可能跟JDK版本过低有关。于是,现场将JDK版本升级到JDK8-432,上述异常现象未再出现!
受限于时间关系,本文并未对底层的根本原因进行深究。至此,本文对问题的分析、定位、解决等步骤记录完成。无论如何,在经济下行企业降本增效的背景下,希望Spark Native加速技术能够发挥一定作用吧。