作者:余建涛,大数据平台产品中心高级工程师

摘要

Spark UI是查看Spark作业运行情况的重要窗口,用户经常需要根据UI上的信息来判断作业失败的原因或者分析作业如何优化。DLC团队实现了云原生的Spark UI Sevice,相较于开源的Spark History Server,存储成本降低80%,大规模作业UI加载速度提升70%。目前已在公有云多个地域上线,为DLC用户提供Spark UI服务。

背景

Spark History Server原理

Spark History Server(以下简称SHS)是Spark原生的UI服务,为了更好了解本文工作的背景,这里先简单介绍下SHS的原理。概况来讲,SHS建立在Spark事件(Spark Event)之上,通过持久化和回放Spark Event来还原Spark作业当前的状态和运行过程中的统计信息。

图1 原生Spark History Server原理

如图1左侧,在作业运行过程中,Spark Driver内部各模块会不断产生与作业运行相关的事件,如ApplicationStart/ApplicationEnd,JobStart/JobEnd,StageStart/StageEnd,TaskStart/TaskEnd等,所有事件都会发送到LiveListenerBus,然后在LiveListenerBus内部分发到各个子队列,由子队列上注册的Listener来处理。SHS实现了EventLogQueue队列和监听该队列的EventLoggingListener,EventLoggingListener负责将Event序列化为Json格式,然后由EventLogFileWriter持久化到Event Log文件。Event Log文件通常通常存储在分布式文件系统。

图1右侧是Spark History Server,在其内部FsHistoryProvider负责事件回放,即将事件反序列化后发送到ReplayListenerBus,然后由相应的Listener处理。这里主要包含两个过程,首先是Application listing,FsHistoryProvider启动一个线程间歇性地扫描Event Log目录下的所有Application目录,检查log文件是否有更新,对于有更新的Application,则读取Event log,通过AppListingListener回放部分事件提取Application运行的概要信息,存储到KVStore。其次是Loading UI,当用户访问UI时从KVStore中查找请求的Application,如果存在,则完整读取Application目录下的 Event Log 文件,再通过 AppStatusListener从事件中提取运行数据然后更新到 KVStore中,还原任务当前的状态信息。WebUI从KvStore查询所需要的数据,实现页面的渲染。

痛点

存储开销大

Spark作业运行过程中每个Task都会产生相关事件,也就说作业越复杂,Task数越多,产生的事件也会越多。其次Event以json格式序列化,导致占用空间也较大。实际生产中,一个大规模作业的Event Log可以达到数十G。

回放效率低

SHS通过解析回放Event Log来还原Spark作业的状态信息,大量事件的反序列化处理开销大,UI加载延迟明显。对于大规模的作业,从发起访问到看到UI,用户可能需要等待数分钟甚至几十分钟,体验较差。

扩展性差

SHS服务节点通过定期扫描Event log目录,在本地KVStore更新维护Application列表,是一个有状态的服务。每次服务重启,需要重新扫描整个目录,才能对外服务。当目录下积累的作业日志增多,每一次扫描的耗时也会相应增加,此外,日志文件合并、清理负担也会加大,必须对服务节点进行纵向扩容。

不支持多租户

在公有云DLC产品中,我们希望为用户提供SAAS化的Spark UI服务,用户无需自己搭建SHS。一种方案是由服务方为每个用户搭建一套SHS,显然成本会很高,同时也会增加维护的负担;如果一个地域只部署一套SHS,一方面要求服务能通过水平扩展提升处理能力,另外还要求服务支持用户间的资源隔离,比如Event log目录、访问权限,开源SHS不具备相关能力。

DLC UI Service

方案

Spark Driver在运行过程中本身就会通过AppStatusListener监听事件并将作业运行的状态数据存储到ElementTrackingStore(数据存储在基于内存的KVStore),以便跟踪作业的运行情况。History Server回放Event log其实是重复这一过程。如果在作业运行过程中直接将状态数据持久化到FileSystem,这样就不用再存储大量Event了。

org.apache.spark.status.JobDataWrapper
org.apache.spark.status.ExecutorStageSummaryWrapper
org.apache.spark.status.ApplicationInfoWrapper
org.apache.spark.status.PoolData
org.apache.spark.status.ExecutorSummaryWrapper
org.apache.spark.status.StageDataWrapper
org.apache.spark.status.AppSummary
org.apache.spark.status.RDDOperationGraphWrapper
org.apache.spark.status.TaskDataWrapper
org.apache.spark.status.ApplicationEnvironmentInfoWrapper# SQL
org.apache.spark.sql.execution.ui.SQLExecutionUIData
org.apache.spark.sql.execution.ui.SparkPlanGraphWrapper# Structure Streaming
org.apache.spark.sql.streaming.ui.StreamingQueryData
org.apache.spark.sql.streaming.ui.StreamingQueryProgressWrapper

图2 运行状态数据类

基于上述朴素的想法,我们设计了如下方案。

图3   DLC Spark UI Service

  1. UIMetaListener

UIMetaListener创建一个ElementTrackingStore实例,用作Temp Store。通过一个线程定期遍历Original ElementTrackingStore中的数据,对于每一条数据,检查Temp Store是否存在相同key的旧数据。若不存在,就将数据写入Backup Store,然后再写出到UI Meta文件;若存在则计算两条数据的MD5并进行对比,若不一致,说明数据已更新,就将新的数据写入Backup Store,然后再写出到UI Meta文件。

图4 Dump UI Meta

Temp Store用于临时存储可能还会发生变化的数据,而对于已经完成的Job/Stage/Task,其状态数据不会再变,而且已经持久化到UI Meta文件,因此需要及时将其从Temp Store清理掉,避免占用太多内存资源。UIMetaListener通过两种方式触发清理,一种是监听到TaskStart/TaskEnd事件时触发,一种是往Temp Store写入数据时触发。

  1. UIMetaWriter

UIMetaWriter定义了UI Meta文件的数据结构,单条结构如下:

图5 数据结构

每个UI相关的数据类实例会序列化成四个部分:类名长度(4字节整型)+ 类型(字符串类型)+ 数据长度(4字节整型)+ 序列化数据(二进制类型)。数据的序列化使用Spark自带的序列化器KVStoreSerializer,支持GZIP压缩。数据在文件中连续存放。

DLC使用对象存储COS来存储UI Meta文件,COS对Append方式写存在诸多限制,同时为了避免Streaming场景下单个文件过大,DLC Spark UI Service实现了RollingUIMetaWriter,支持按文件大小滚动写;同时也实现了SingleUIMetaWriter,适用于支持Append写和对文件个数敏感的文件系统,比如HDFS。

  1. UIMetaProvider

UIMetaProvider重新实现了ApplicationHistoryProvider,去掉了FsHistoryProvider里的日志路径定期扫描,不再维护全量的Application列表。当收到某个Application UI请求时,UIMetaProvider根据路径规则直接读取对应Application目录下的UI Meta文件,反序列化数据并写入KVStore。简化后的History Server只需要处理加载UI的请求,因此很容易通过水平扩展提升服务整体的处理能力。

跟FsHistoryProvider一样,UIMetaProvider也支持缓存已加载的Active UI数据。但不同的是,对于缓存中的Active UI,UIMetaProvider会定期检查对应的作业状态或日志文件是否有变化,如果有则自动读取新增的UI Meta文件,更新KVStore里的数据,无需每次都从头开始加载。

  1. 多租户

原生SHS没有多租户设计,默认所有的作业日志都存放在同一个目录下,ACL由每个作业在其运行参数里设置。而DLC为不同用户分配了不同的日志目录,同时希望基于公有云账号进行认证和鉴权,为此Spark UI Service做了一些改造。

用户通过DLC访问Spark UI Service时,首先跳转到公有云登陆入口,完成登陆后在请求cookie中添加userId。Spark UI Service通过HttpRequestUserFilter拦截请求,将Cookie中携带的userId保存在请求处理线程的ThreadLocal变量中。在加载UI Meta时根据userId查询用户的日志目录,然后拼接请求参数中携带的appId和attemptId组成完整的日志路径。同时在缓存Active UI时也会将userId信息随之保存,当命中缓存中UI时也要校验userId和请求中携带的userId是否一致。

测试结果

以SparkPi作为测试作业,分别在四种参数下进行测试。如下图所示,DLC Spark UI Serice相较于开源Spark History Server,日志大小减少了80%,大型作业的UI加载时间减少70%,用户体验明显改善。

图6 日志大小对比

图7 UI加载时间对比

总结

针对云原生场景下的Spark UI需求,DLC重新设计了Spark UI Service方案,并对开源Spark进行了改造,从成本上降低了日志存储开销,从用户体验上加速了UI访问,从架构上实现了服务的水平扩展。

推荐阅读

关注腾讯云大数据公众号

邀您探索数据的无限可能

点击“阅读原文”,了解相关产品最新动态

↓↓↓

云原生Spark UI Service在腾讯云云原生数据湖产品DLC的实践相关推荐

  1. 国内首批!阿里云云原生数据湖产品通过信通院评测认证

    近日,中国信息通信研究院 (以下简称"信通院") 正式公布了第十四批"大数据产品能力评测"结果,阿里云云原生数据湖产品,包括云原生开源大数据平台 E-MapRe ...

  2. 极客星球 | 阿里:云原生数据湖构建与分析实践

    编者按:6月24日[Coder Park]第一季架构篇之大数据平台架构分享线上直播活动圆满结束.本期特邀MobTech袤博科技合伙人.首席数据官杨冠军担当出品人,阿里巴巴计算平台事业部大数据平台技术专 ...

  3. StarLake:汇量科技云原生数据湖的探索和实践

    简介: 快速了解汇量科技在云原生数据湖领域的探索和实践,详解 StarLake 的架构及业务应用案例. 作者:陈绪(汇量科技资深算法架构师,EnginePlus 2.0 产品负责人) 内容框架: 互联 ...

  4. 云原生数据湖为什么要选择腾讯云大数据DLC,一份性能分析报告告诉你!

    摘要 日前,腾讯云大数据数据湖计算 DLC 与国内两家知名云厂商的数据湖产品进行了性能对比,其中腾讯云 DLC 在三款产品中SQL平均执行查询时间短,性能表现优.腾讯云大数据 DLC 在存算分离和大数 ...

  5. 一份数据满足所有数据场景?腾讯云数据湖解决方案及DLC内核技术介绍

    摘要 OLAP数据库/引擎日新月异,不断推陈出新,在各种场景下有不同引擎的价值:flink擅长于实时数据集成/实时计算:spark批处理.tb级以上.hive生态.复杂join的数据分析.以及机器学习 ...

  6. 腾讯云首次披露云原生智能数据湖全景图,数据湖之争再起波澜

    (图片下载自视觉中国) 数据湖并不是一个很有历史感的概念,从2010年才首次被Pentaho创始人兼首席技术官詹姆斯·狄克逊(James Dixon)提出,至今发展仅有十多年,但已经成为一个谈到大数据 ...

  7. 【2022分布式存储峰会】腾讯云存储为您带来:云原生时代下的数据湖存储服务

    大会时间:今日15:00-15:30 大会主题:云原生时代下的数据湖存储服务 2022年4月14日,由百易传媒 (DOIT) 与厦门大学信息学院联合主办的"2022分布式存储论坛峰会&quo ...

  8. 如何用好云原生数据湖?

    简介:数据湖可以很好地帮助企业应对当前数据场景越来越多.数据结构越来越复杂.数据处理需求越来越多样化的问题.阿里云从2018年起就开始布局数据湖,推出了云原生数据湖分析Data Lake Analyt ...

  9. 听说,难于上青天的云原生数据湖能开箱即用了?

    导语 | 云原生数据湖架构以低成本优势推动客户上云,同时云上客户得以低成本撬动更多结构化和非结构化数据的价值,是一场云厂商的自我革命.本文由腾讯大数据专家工程师于华丽在 Techo TVP开发者峰会「 ...

最新文章

  1. linux下几种文件系统的测试比较
  2. git 硬回滚和软回滚
  3. linux shell 计算器 除0,用shell写一个简易计算器,可以实现加、减、乘、除运算,假如脚本名字为1.sh,执行示例:./1....
  4. android studio闪退代码不报错_代码不报错,不代表真的没错
  5. 百练 03 复杂的整数划分问题
  6. 为了找工作的学习计划
  7. 感知器模型为什么不能解决异或问题
  8. 可视化分析:洞见数据的秘诀
  9. 【数据结构笔记】归并排序(merge_sort)+ 堆排序 -- python2.7
  10. 因式分解题目及过程_两道新定义题目的对比分析
  11. windows虚拟显示器开发(三)USB显示器
  12. 如何读取通用配置文件conf?
  13. 遇到 *.7z001 *.7z.002 *.7z.003 如何用winrar解压缩
  14. 始终从最不易改变的方面开始
  15. Android实时语音聊天
  16. 数值型数据的表示(2.0)
  17. 微软官方给出无法安装WIN10更新的终极解决办法:覆盖安装
  18. mdadm 创建md 删除md步骤
  19. php微信退款 v3版,微信支付-JSAPI支付V3-查询退款
  20. 公网IP和内网IP的区别

热门文章

  1. 150家老字号现身故宫!文具、美食……还有啥?
  2. 快速排斥实验amp;跨立实验 判断两直线是否相交
  3. 为php文件建立ip地址,IP地址查询网站的建立(基于qqwry数据库建立)
  4. System.getProperty()方法获取系统变量
  5. ListBox 的SelectedValuePath和 SeletedValue 以及SelectedItem的关系
  6. WPS表格使用VBA链接SQLServer读取数据
  7. 【转】采用 Linux* Containers 的单根输入/输出虚拟化 (SR-IOV)
  8. 迭代阈值法,otsu阈值法,特征空间类聚法对图像进行分割(python)
  9. 低亮度人脸检测、附源码——CVPR2021之 Low Light Face Detection【一文读懂】
  10. 你应该知道的云计算行业最专业的教材