前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >云原生Spark UI Service在腾讯云云原生数据湖产品DLC的实践

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

作者头像
腾讯云大数据
发布2022-08-26 16:13:14
1.3K0
发布2022-08-26 16:13:14
举报
文章被收录于专栏:腾讯云大数据腾讯云大数据

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

摘要

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了。

代码语言:javascript
复制
org.apache.spark.status.JobDataWrapperorg.apache.spark.status.ExecutorStageSummaryWrapperorg.apache.spark.status.ApplicationInfoWrapperorg.apache.spark.status.PoolDataorg.apache.spark.status.ExecutorSummaryWrapperorg.apache.spark.status.StageDataWrapperorg.apache.spark.status.AppSummaryorg.apache.spark.status.RDDOperationGraphWrapperorg.apache.spark.status.TaskDataWrapperorg.apache.spark.status.ApplicationEnvironmentInfoWrapper
# SQLorg.apache.spark.sql.execution.ui.SQLExecutionUIDataorg.apache.spark.sql.execution.ui.SparkPlanGraphWrapper
# Structure Streamingorg.apache.spark.sql.streaming.ui.StreamingQueryDataorg.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访问,从架构上实现了服务的水平扩展。

推荐阅读

关注腾讯云大数据公众号

邀您探索数据的无限可能

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

↓↓↓

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2022-08-05,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 腾讯云大数据 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 作者:余建涛,大数据平台产品中心高级工程师
  • 摘要
  • 背景
    • Spark History Server原理
      • 痛点
        • 存储开销大
        • 回放效率低
        • 扩展性差
        • 不支持多租户
    • DLC UI Service
      • 方案
        • 测试结果
        • 总结
        相关产品与服务
        文件存储
        文件存储(Cloud File Storage,CFS)为您提供安全可靠、可扩展的共享文件存储服务。文件存储可与腾讯云服务器、容器服务、批量计算等服务搭配使用,为多个计算节点提供容量和性能可弹性扩展的高性能共享存储。腾讯云文件存储的管理界面简单、易使用,可实现对现有应用的无缝集成;按实际用量付费,为您节约成本,简化 IT 运维工作。
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档