转载自程序员小陶

Apache DolphinScheduler 在使用过程中,肯定会有任务出现失败的情况,那么问题来了:调度任务的告警是需要人为配置的,在生产环境中,面对海量的任务,如何找到重要的任务,并且在失败的时候,第一时间告警呢?

先思考一下。

先看思路

本文提供一个思路,接着往下看吧。

不卖关子了。

本质是路径查找,本文这里使用了图数据库,或者你也可以自己使用Java实现路径查找。

下面是需要实现的目标,看一组任务的关系,如下图所示,存在 A/B/C/D/E 五个任务,E 任务被配置为核心任务,当 B 任务报错时,检测到 B 和 E 之前存在路径,则需要电话告警。

所以在配置核心链路告警的时候,我们只需要配置叶子节点,在实际生产中,一般是应用层的任务,比如报表、标签、接口数据等任务。

清洗依赖数据

核心逻辑就是把所有工作流内部、跨工作流以及跨项目的依赖全部清洗出来,生成一张关系表。具体清洗逻辑,可以看:海豚调度监控:新增依赖缺失巡检,上游改动再也不用担心了!

最终生成了

t_ds_task_node_base_data 任务基础表,后续会用于 Nebula Graph,这个后面会讲。

t_ds_dag_task_relation_data_df 关系最终表,后续会用于 Nebula Graph,这个后面会讲。

t_ds_dag_task_relation_data_df 这个表结构如下:

关系导入图数据库

这里用的国产图数据库 Nebula Graph,当然你也可以自己使用 Java 实现路径查找。

为什么我们一定要引入图数据库呢?有下面几方面考虑:

  • 可以减轻调度系统Mysql的压力,把负责的路径计算放在图数据库里面。
  • 探索更多调度任务数据治理和运维的可能性,比如任务权重,影响分析等。

用到的组件是 Nebula Graph,最关键的函数是 find path 查询最短链路

① 用到的语法是:FIND SHORTEST PATH需要注意的是,注意查询步长,UPTO <N> {STEP|STEPS}:路径的最大跳数。默认值为5。

② 3.3.0 开始,子图支持了边的条件限制了,查询的时候只拿最新的一批关系。

  • 创建图空间
CREATE SPACE s_schedule_job (partition_num = 225, replica_factor = 3, vid_type = FIXED_STRING(180)) COMMENT = "大数据平台调度系统任务的血缘关系";
  • 创建边和点
## 任务标签

DROP tag if exists t_task;
CREATE tag if not exists t_task( id string NULL COMMENT "project_code,dag_code,task_code,拼接,", project_name string NULL COMMENT "project_name", project_code string NULL COMMENT "project_code", dag_name string NULL COMMENT "dag_name", dag_code string NULL COMMENT "dag_code", dag_version string NULL COMMENT "dag_version", task_code string NULL COMMENT "task_code", task_version string NULL COMMENT "task_version", task_name string NULL COMMENT "task_name", task_type string NULL COMMENT "task_type", create_time string NULL COMMENT "时间戳") comment='调度任务节点'; ## 调度任务关系
drop edge if exists e_task;
create edge if not exists e_task( pre_project_name string NULL COMMENT "project_name", pre_project_code string NULL COMMENT "project_code", pre_dag_name string NULL COMMENT "dag_name", pre_dag_code string NULL COMMENT "dag_code", pre_dag_version string NULL COMMENT "dag_version", pre_task_code string NULL COMMENT "task_code", pre_task_version string NULL COMMENT "task_version", pre_task_name string NULL COMMENT "task_name", pre_task_type string NULL COMMENT "task_type", post_project_name string NULL COMMENT "project_name", post_project_code string NULL COMMENT "project_code", post_dag_name string NULL COMMENT "dag_name", post_dag_code string NULL COMMENT "dag_code", post_dag_version string NULL COMMENT "dag_version", post_task_code string NULL COMMENT "task_code", post_task_version string NULL COMMENT "task_version", post_task_name string NULL COMMENT "task_name", post_task_type string NULL COMMENT "task_type", create_time string NULL COMMENT "时间戳") comment='调度任务关系';
  • 导入数据
同步点:

{
spark: {
app: {
name: Nebula_Exchange_t_task
}
driver: {
cores: 2
maxResultSize: 5G
}
} nebula: {
address:{
graph:["10.1.x.xx:9669","10.1.x.xx:9669","10.1.x.xx:9669","10.1.x.xx3:9669","10.1.x.xx:9669"]
meta:["10.1.x.xx:9559","10.1.x.xx:9559","10.1.x.xx:9559"]
}
user: root
pswd: "nebula密码"
space: s_schedule_job
connection {
timeout: 60000
retry: 3
}
execution {
retry: 3
}
error: {
max: 32
output: /tmp/errors/t_task
}
rate: {
limit: 1024
timeout: 10000
}
}
tags: [ {
name: t_task
type: {
source: mysql
sink: client
}
host:"调度系统MYSQL数据库IP"
port:3307
database:"调度系统MYSQL数据库"
table:"t_ds_task_node_base_data"
user:"调度系统MYSQL用户"
password:"调度系统MYSQL用户密码"
sentence:"SELECT concat(project_code,'_',dag_code,'_',task_code) as id,project_name,project_code,dag_name,dag_code,dag_version,task_code,task_version,task_name,task_type,create_time FROM t_ds_task_node_base_data"
fields: [project_name,project_code,dag_name,dag_code,dag_version,task_code,task_version,task_name,task_type,create_time]
nebula.fields: [project_name,project_code,dag_name,dag_code,dag_version,task_code,task_version,task_name,task_type,create_time]
vertex:{
field:id
}
batch: 256
partition: 32
} ] }

同步边:

{
spark: {
app: {
name: Nebula_Exchange_e_task
}
driver: {
cores: 2
maxResultSize: 5G
}
} nebula: {
address:{
graph:["10.1.x.xx:9669","10.1.x.xx:9669","10.1.x.xx:9669","10.1.x.xx3:9669","10.1.x.xx:9669"]
meta:["10.1.x.xx:9559","10.1.x.xx:9559","10.1.x.xx:9559"]
}
user: root
pswd: "aD@VX2018#"
space: s_schedule_job
connection {
timeout: 60000
retry: 3
}
execution {
retry: 3
}
error: {
max: 32
output: /tmp/errors/e_task
}
rate: {
limit: 1024
timeout: 10000
}
}
edges: [ {
name: e_task
type: {
source: mysql
sink: client
}
host:"调度系统MYSQL数据库IP"
port:3307
database:"调度系统MYSQL数据库"
table:"t_ds_task_node_base_data"
user:"调度系统MYSQL用户"
password:"调度系统MYSQL用户密码"
sentence:"SELECT concat(pre_project_code,'_',pre_dag_code,'_',pre_task_code) as from_id,concat(post_project_code,'_',post_dag_code,'_',post_task_code) as to_id,pre_project_name,pre_project_code,pre_dag_name,pre_dag_code,pre_dag_version,pre_task_code,pre_task_name,pre_task_type,pre_task_version,post_project_name,post_project_code,post_dag_name,post_dag_code,post_dag_version,post_task_code,post_task_name,post_task_type,post_task_version,create_time FROM t_ds_dag_task_relation_data_df"
fields: [pre_project_name,pre_project_code,pre_dag_name,pre_dag_code,pre_dag_version,pre_task_code,pre_task_name,pre_task_type,pre_task_version,post_project_name,post_project_code,post_dag_name,post_dag_code,post_dag_version,post_task_code,post_task_name,post_task_type,post_task_version,create_time]
nebula.fields: [pre_project_name,pre_project_code,pre_dag_name,pre_dag_code,pre_dag_version,pre_task_code,pre_task_name,pre_task_type,pre_task_version,post_project_name,post_project_code,post_dag_name,post_dag_code,post_dag_version,post_task_code,post_task_name,post_task_type,post_task_version,create_time]
source: {
field: from_id
}
target: {
field: to_id
}
batch: 256
partition: 225
} ] }

定时脚本: 使用 Nebula Graph 社区提供的 exchange 工具把数据从 mysql 导入 Nebula Graph。

#!/bin/bash
# 作业参数
basepath='/opt/vcredit-graph-db/s_schedule_job/exchange'
tmpdir='/tmp/nebula/s_schedule_job'
mkdir -p $tmpdir
sourcefile=${basepath}/${jobname}.conf
targetfile=${tmpdir}/${jobname}_${vardate}.conf
cat ${sourcefile} > ${targetfile}
sed -i "s/vardate/${vardate}/g" ${targetfile}
sed -i "s/varhivetable/${varhivetable}/g" ${targetfile} # 运行环境
export JAVA_HOME=/usr/java/jdk1.8.0_181-cloudera
spark_submit="/opt/spark-2.4.8-bin-hadoop2.7/bin/spark-submit"
# 开始运行
${spark_submit} \
--principal hive@VCREDIT.COM \
--keytab /etc/security/hive.keytab \
--master "local[*]" \
--class com.vesoft.nebula.exchange.Exchange /opt/nebula/nebula-exchange_spark_2.4-3.0.0.jar -c ${targetfile} -h

Java 服务

/**
* 判断这个任务是否会影响核心任务
* @param projectName
* @param dagName
* @param taskName
* @return
*/
@ApiOperation(value = "dolphinTaskIsOnCall", notes = "判断这个任务是否会影响核心任务,是 1 ,否 0")
@ApiImplicitParams({
@ApiImplicitParam(name = "projectName", value = "T-1", required = false, dataType = "String", example = "BigData"),
@ApiImplicitParam(name = "dagName", value = "T-1", required = false, dataType = "String", example = "公共和自定义域(pub)_daily"),
@ApiImplicitParam(name = "taskName", value = "T-1", required = false, dataType = "String", example = "dwd_pub_screen_zxd_cust_df")
})
@GetMapping("/dolphinTaskIsOnCall")
@ResponseBody
public DataResult dolphinTaskIsOnCall(
@RequestParam(value = "projectName", required = true) String projectName,
@RequestParam(value = "dagName", required = true) String dagName,
@RequestParam(value = "taskName", required = true) String taskName) throws GraphDatabaseException, UnsupportedEncodingException { HashMap<String,Object> res = dolphinService.dolphinTaskIsOnCall(projectName, dagName, taskName);
return DataResult.ok(res);
}

核心代码,在第 17 行:

@Override
public HashMap<String, Object> dolphinTaskIsOnCall(String projectName, String dagName, String taskName) throws GraphDatabaseException, UnsupportedEncodingException {
HashMap<String,Object> resMap = new HashMap<>();
// 查询该任务 codes
HashMap<String,Object> task = dolphinTaskInstanceMapper.getTaskCode(projectName,dagName,taskName);
if (task == null){
resMap.put("res","任务不存在!");
return resMap;
}
String fromCodes = task.get("project_code") + "_" + task.get("dag_code") + "_" + task.get("task_code");
// 查询核心任务 codes
List<HashMap<String,Object>> tasks = dolphinTaskInstanceMapper.getOnCallTasks();
// 查询最短链路
for (HashMap<String,Object> t : tasks){
String toCodes = t.get("project_code") + "_" + t.get("dag_code") + "_" + t.get("task_code");
// 查询Nebula
String NgSql = "FIND SHORTEST PATH with PROP FROM \"" + fromCodes + "\" TO \"" + toCodes + "\" OVER * WHERE e_task.create_time > '" + DateUtils.dayToString(DateUtils.getSomeDay(new Date(), -1)) + "' UPTO 100 STEPS YIELD path AS p;";
int res = nebulaService.isOnCallTask("s_schedule_job",NgSql);
if (res > 0){
resMap.put("res",res);
return resMap;
}
}
resMap.put("res",0);
return resMap;
}

返回值说明:

① 影响核心任务,需要打电话

② 不影响核心任务,不需要打电话

③ 任务不存在,忽略

④ code 不等于 0 ,接口异常,忽略。

封装好接口之后,任务失败的程序调这个接口,判断失败任务是否影响核心任务,如果影响就打电话。

钉钉告警样式:

电话告警,直接给对应负责人打电话。

至此,我们减少了很多任务告警的配置工作,只需要关注核心的叶子节点是什么,也就是核心的应用任务是什么,大大提高了任务告警的配置效率!!!

  • 注意:清洗数据 和 导入图数据库,在每天的 23:30 分进行,一天初始化一次,确保凌晨的任务关系是最新的,主要是用于凌晨告警。

以上就使用图关系网络解决核心链路告警的全部内容,如果有任何疑问,都可以与我交流,希望可以帮到你,下次见。

原文链接:https://blog.csdn.net/qq_31975963/article/details/139839102

本文由 白鲸开源 提供发布支持!

Apache DolphinScheduler使用图关系解决核心链路告警问题,减轻任务运维负担!的更多相关文章

  1. 解决CentOS无法显示中文字体 | 系统运维 | Web2.0

    解决CentOS无法显示中文字体 | 系统运维 | Web2.0 About Me    博客园    devops    前端    张家港水蜜桃 傍晚好! 2013年09月12日 17:56:08 ...

  2. 看DLI服务4核心如何提升云服务自动化运维

    摘要:今天我们来说说DLI是如何实现监控告警来提升整体运维能力,从而为客户更好的提供Serverless的DLI. DLI是支持多模引擎的Serverless大数据计算服务,免运维也是其作为Serve ...

  3. 日均 6000+ 实例,TB 级数据流量,Apache DolphinScheduler 如何做联通医疗大数据平台的“顶梁柱”?

    作者 | 胡泽康 鄞乐炜 作者简介 胡泽康 联通(广东)产业互联网公司  大数据工程师,专注于开源大数据领域,从事大数据平台研发工作 鄞乐炜 联通(广东)产业互联网公司 大数据工程师,主要从事大数据平 ...

  4. Apache DolphinScheduler(海豚调度) - 1.3 系列核心表结构剖析

    Apache DolphinScheduler 是一个分布式去中心化,易扩展的可视化 DAG 工作流任务调度系统.致力于解决数据处理流程中错综复杂的依赖关系,使调度系统在数据处理流程中开箱即用. 近日 ...

  5. 本周六 Apache DolphinScheduler & Doris 将联合线上 Meetup

    活动背景 2020年,大数据成为国家基建的一个重要组成,大数据在越来越多的领域展现威力.随着大数据的应用场景越来越多,大家对数据的响应速度和数据加工工作流的方便程度也提出了更高的要求.在这种背景下,相 ...

  6. Apache DolphinScheduler之最美好的遇见

    关于 Apache DolphinScheduler社区 Apache DolphinScheduler(incubator) 于17年在易观数科立项,19年3月开源, 19 年8月进入Apache ...

  7. Apache DolphinScheduler & Doris 将于本周六联合进行线上 Meetup

    01 - 活动介绍 2020年,大数据成为国家基建的一个重要组成,大数据在越来越多的领域展现威力.随着大数据的应用场景越来越多,大家对数据的响应速度和数据加工工作流的方便程度也提出了更高的要求.在这种 ...

  8. Apache DolphinScheduler新一代分布式工作流任务调度平台实战-上

    概述 定义 dolphinscheduler 官网地址 https://dolphinscheduler.apache.org/ dolphinscheduler GitHub地址 https://g ...

  9. Apache DolphinScheduler 2.X保姆级源码解析,中国移动工程师揭秘服务调度启动全流程

    2022年1月,科学技术部高新技术司副司长梅建平在"第六届中国新金融高峰论坛"上表示,当前数据量已经大大超过了处理能力的上限,若信息技术仍然是渐进式发展,则数据处理能力的提升将远远 ...

  10. 论语音社交视频直播平台与 Apache DolphinScheduler 的适配度有多高

    在 Apache DolphinScheduler& Apache ShenYu(Incubating) Meetup 上,YY 直播 软件工程师 袁丙泽 为我们分享了<YY直播基于Ap ...

随机推荐

  1. 一行超长日志引发的 “血案” - Containerd 频繁 OOM 背后的真相

    案发现场:混沌初现 2024年6月10日,本应是平静的一天.但从上午 9 点开始,Sealos 公有云的运维监控告警就开始不停地响.北京可用区服务器节点突然出现大量 "not ready&q ...

  2. 20-Docker镜像制作

    查看镜像构建的历史 docker image history 26a5 #查看镜像26a5的构建历史 使用commit命令构建镜像 使用commit命令可以将容器构建成镜像. 将容器webserver ...

  3. 用Tensorboard在VScode Remote ssh中显示图像

    可以用Tensorboard在vscode的ssh连接中显示plot出的图像. 具体方法如下: from torch.utils.tensorboard import SummaryWriter wr ...

  4. c/c++:带有返回类型的函数没有return语句会怎么样?

    c/c++:带有返回类型的函数没有return语句会怎么样 背景 机器有时候启动的时候发现异常,跟踪了代码发现,有人在写一个int函数的时候,有一个分支没有return: 参考:https://www ...

  5. Simple WPF: WPF 透明窗体和鼠标事件穿透

    一个自定义WPF窗体的解决方案,借鉴了吕毅老师的WPF制作高性能的透明背景的异形窗口一文,并在此基础上增加了鼠标穿透的功能.可以使得透明窗体的鼠标事件穿透到下层,在下层窗体中响应. 这个方法不一定是制 ...

  6. C#开发单实例应用程序并响应后续进程启动参数

    C#默认的WinForm模板是不支持设置单实例的,也没有隔壁大哥VB.NET那样有个"生成单个实例应用程序"的勾选选项(VB某些时候要比C#更方便),实现单实例可以有多种方法: 检 ...

  7. GitHub 创始人资助的开源浏览器「GitHub 热点速览」

    你是否注意到,现在主流的浏览器如 Chrome.Edge.Brave 和 Opera 都采用了谷歌的 Chromium 引擎?同时,谷歌每年不惜花费数十亿美元,确保其搜索引擎在 Safari 中的默认 ...

  8. MyBatis-Plus 整理

    # 前言 代码生成器插件选择去这里:https://www.cnblogs.com/zixq/p/16726534.html 相关插件在那里面已经提到了 # 上手 MyBatis-Plus 是一个 M ...

  9. django 如何查询汇总的求和时避免没有数据导致的错误

    django 如何查询汇总的求和时避免没有数据导致的错误 在 Django 中,如果你希望对某个字段进行求和操作,并在没有数据时返回默认值,可以使用 aggregate 结合 Coalesce 函数. ...

  10. 开启GitLab的邮件通知功能以及一些外观配置

    前言 维护GitLab的同事离职了 刚好又有新实习生需要申请账号 只能我来出手了 其实之前安装了 GitLab 之后一直还是用得比较粗糙的 属于是勉强能用的水平,有些配置都还没改好 这次把邮件功能.域 ...