共计 3541 个字符,预计需要花费 9 分钟才能阅读完成。
大家好我是张金明,在蔚来汽车负责大数据平台研发工程师。这次和大家分享的是 Apache DolphinScheduler 在蔚来汽车一站式数据治理开发平台的利用和革新,接下来我将从背景、利用现状和技术改造三个方面去分享一下。
背景
业务痛点
在蔚来汽车构建一个对立的数据中台之前,咱们面临这样一些业务痛点和窘境:
数据不足治理,数仓不标准、不残缺
- 没有对立的数据仓库,无全域的数据资产视图
- 存在数据孤岛;
工具散乱,用户权限不对立、学习老本高
- 用户须要在多个工具之间切换,导致开发效率升高
- 底层运维老本高;
数据需要响应周期长,找数难、取数难
- 无沉淀的数据资产与中台能力,反复解决原始数据;
- 业务数据需要从提出到获取后果的周期长
基于这些痛点和问题,咱们构建了一个公司层面的业务中台,外部叫做 DataSight。
咱们能够看到,最底下是咱们的一些根底组件;往上一层,这些根底组件次要是撑持了一些数据接入与开发的模块;再向上是咱们的数据治理,以及数据资产与应用层。其中,Apache DolphinScheduler 这个调度器在公司次要利用于交互的模块,就是数据开发和数据运维两个模块。
数据开发中,调度工作开发次要就是用到了 Apache DolphinScheduler,通过 API 和调度器进行交互。
利用现状
作业现状
目前,咱们的机器共有 9 台,别离是两台 Master 机器,是 8c 和 32G;六台 Worker 机器,16c 和 64G,以及一台 Alert 机器,8c 和 32G。
版本是更新到了 Apache DolphinScheduler 2.0.7,后续的指标是降级到 2.0.8 版本,2.0 版本曾经可能撑持咱们的业务了,整体的稳定性还是比拟好的。
咱们其实是从 2022 年 4 月份开始才真正地在线上运行 Apache DolphinScheduler,直到明天大略运行了一年一个月多的工夫,日均的调度工作流实例大略在 4w+,日均调度工作实例大略在 10w+ 左右,次要节点是 Spark 节点、SparkSQL、prestoSQL、Python 和 Shell,其中 Spark 节点占比约 70%。
目前这些节点曾经可能撑持咱们的大部分业务,后续咱们可能会把 DolphinScheduler 自带的一些节点加到咱们的数据开发模块外面来。
技术改造
为了适应咱们业务的需要,咱们对 Apache DolphinScheduler 进行了一些技术改造。首先是稳定性方面的工作。
稳定性
- 滚动重启 + 黑名单机制 + 精准路由
这个革新是因为咱们遇到的一些痛点,首先,大家晓得,DolphinScheduler 的 Worker 重启机制在重启时会把所有的工作给 kill 掉,而后去 Restart 这个工作,把这个 kill 的工作散发到新的 Worker 机器上。这样会导致工作执行工夫较长。这不合乎咱们的预期。
同时,咱们也无奈在特定的 Worker 上进行验证工作。
对此,咱们的解决方案就是滚动重启,在重启某台机器之前先下线这台机器,也就是加上黑名单,这样的话,Master 机器就不会给这台下曾经下线的机器去散发 worker 工作。这台机器会在下面的工作全副处理完毕后主动上线,也就是移出这个黑名单。接下来所有的 woker 节点都依照此种形式重启,达到平滑重启的目标。
这样做的益处在于不会阻塞每个工作的执行,集群在重启的时候稳定性能失去大幅晋升。
另外,咱们还做了精准路由的工作。也就是在工作名后加特定后缀,实现精准路由到某台机器上。
如图所示,咱们在这个工作前面加一个 specific dispatch-worker02 的话,那这个工作肯定会被调配到 Worker02 这台机器下来。这样的益处在于,假如咱们想要去某一个性能点,咱们只须要把某一台 Worker 机器下线重启,须要测试的性能点依照这个形式就肯定可能打到这台特定的机器下来,实现最小范畴的灰度,有助于进步稳定性。
- 优化存储
在存储方面,咱们痛点也很显著,就是 process instance 和 task instance 这两张表数据量是比拟大的,因为咱们每天的数据量比拟大,目前曾经达到了千万级别,造成 MySQL 的存储压力比拟大。另外,局部 SQL 执行工夫长,业务响应变慢;而且 DDL 时会造成锁表,导致业务不可用。
针对这些问题,咱们的解决方案包含去梳理所有的慢 SQL,而后去增加适合的索引。与此同时,还有升高查问频率,特地是针对依赖节点。因为咱们晓得依赖节点每 5 秒钟查问一次数据库,所以咱们依据依赖节点所在的 tasks instance ID 去做一个“打散”,偶数节点每 30 秒查问一次,奇数节点每 30 秒查问一次,把他们离开来升高对整个数据库的查问压力。
另外,为了加重表数据量大的问题,咱们也做了一个定期删除的策略,以及定时同步历史数据的策略。
定时删除就是咱们利用 DolphinScheduler 本身的调度能力建设两个工作流去删除这两张表,保障 process instance 这张表保留两个月的数据,task instance 这张表保留一个月的数据。同时在删表的时候,咱们要留神在非业务高峰期时去做这个动作,每次删表的时候,batch size 要管制好,尽量不要影响线上的工作。
定时同步历史数据,就是咱们针对 process instance 这个表,根据 schedule time 按年去分表;针对 task instance 这张表,按 first submit time 按月去分表。
- Spark 工作优化
咱们提交 Spark 工作的形式是通过 Sparks Submit 去提交的,它的毛病在于提交 Spark 工作后,常驻机器,导致机器内存过大,会有机器宕机的危险,worker 的运行效率较低。
咱们优化了 Spark 工作提交和运行的逻辑,就是通过 Spark Submit 提交的时候增加 spark.yarn.submit.waitAppCompletion=false
这个参数,这样工作提交完当前这个过程就隐没了。思考到要保障 worker 机器工作的线程和 Spark 和 Yarn 上的状态统一,咱们距离肯定工夫查问 Spark 工作状态,如图所示:
这里是一个 while true 循环,首先去判断这个工作是否超时。如果工作曾经超时就会完结这个 Spark 工作,同时会 kill 掉集群上那个真正在跑的工作。
如果工作没有超时,咱们会去获取工作的状态,如果工作状态是终止状态,就间接跳出这个循环,否则会距离肯定的工夫,比方 30 秒,再持续这个 while true 循环。这种形式让整个 worker 机器所能承载的 Spark 工作大大增加。
易用性
接下来再看一些咱们在易用性方面的革新工作吧!
- 依赖节点优化
咱们的依赖节点之前的痛点在于,它的应用规定不太合乎用户的需要,比方之前是单次查问不到上游即失败;日志内容显示信息不全,对用户不敌对;用户无奈自定义依赖范畴。
针对这些问题,咱们做的工作包含批改了查问逻辑为持续期待,就是说当这个工作查问不到上游的时候,咱们会持续期待,而不是间接失败。同时咱们会也有个极其的保障,就是这个依赖节点超过 24 小时当前就让它主动失败,而后给用户发一个报警。
针对依赖节点,咱们也做了强制胜利这样一个小 trick,并反对用户自定义依赖范畴。
另外,咱们还优化了依赖节点的日志输入,当用户点击依赖节点的日志的时候,能够比较清楚地看到依赖的上游所在的空间,这个空间内工作所对应的保护人是什么,以及工作流节点是什么和实现状态,让用户能够点对点地找到上游的同学,疾速解决这个依赖节点卡住的问题。
- 补数工作优化
针对补数之前的痛点,比方补数工作没有进度提醒,
并行补数流程实例不严格依照工夫程序,进行并行补数工作逻辑比拟麻烦等问题,咱们的解决方案包含并行任务引入线程池,也就是把工作依照工夫程序一个一个抛到新建的线程池里,执行结束当前退出这个线程池,而后再放一个新的进来,达到并行补数的状态。同时,执行工夫按递增的程序。
当咱们想进行这个补数工作的时候也比较简单,间接把这个线程池 shutdown 就行。
- 多 SQL 执行
最初是对于多 SQL 执行方面的优化。咱们之前面临的痛点包含:
- 多 SQL 须要多节点执行节约集群资源;
- 自定义环境变量无奈实现;
- 无奈跟踪 SparkSQL 的运行日志。
咱们的解决方案包含拆分这条 SQL,反对多条 SQL 同时执行。
与此同时,咱们能够在 SparkSQL 工作执行之前拦挡执行 select engine_id() as engine_id
语句。
如上图所示,对于 SQL 1 和 SQL 2,之前咱们会在两个工作外面去放着,然而当初能够在一个工作节点外面放下来,它会执行两次。同时咱们能够清晰地看到这个 SparkSQL 所在的 application ID 是什么,用户可能清晰地依据这个 application ID 找这个业务所在的地址,理解这个作业的进度。
本文由 白鲸开源科技 提供公布反对!