ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

DolphinScheduler钉钉预警配置实战:从零接入到踩坑排查

2026/10/4 3:24:10 拓冰建站 浏览量
DolphinScheduler钉钉预警配置实战:从零接入到踩坑排查 上个月我接了个活儿把一套老项目的批处理任务迁到新数据平台上顺手要把海豚调度器DolphinScheduler重新部署起来并且加上钉钉预警。本来以为这活儿半天就能收工——我早在前两份工作里就折腾过这个调度器DAG拖拽、定时触发、任务依赖闭着眼都能配。结果真正动起手来才发现现在的版本跟我记忆里的差别比想象中大尤其是告警这块配置路径、插件逻辑、消息内容全变了旧经验只能算个引子细节全靠重新踩坑。这篇文章就把这次“再次使用”海豚调度器的过程拆开讲重点说清楚钉钉预警从零怎么配、配置背后的原理是什么、以及哪些地方容易翻车。如果你正准备给 DolphinScheduler 加钉钉告警或者你是接手一个已经部署好的调度平台这里应该有你能直接抄的配置步骤和排查思路。1. 再次启用海豚调度器先看版本和告警架构1.1 从旧记忆中跳出来版本演进带来的配置差异我第一次用海豚调度器还是 1.3.x 时代。坦白讲那个版本的告警模块用起来挺费劲告警相关的配置散落在 alert.properties 里加一个钉钉机器人要先改配置、再重启 alert 服务而且当时钉钉接入还属于需要额外启用的选装件注释里写着一堆参数哪个必须填、哪个可以留空全凭运气。后来在另一个项目里用过 2.0.x从那时起告警就开始走向插件化了但说实话很多从 1.x 升上来的老用户还是习惯性去翻配置文件容易走弯路。这次项目用的是 DolphinScheduler 3.1.5变化就更明显了。告警不再是“配置文件里的一段内容”而是变成了“安全中心”里的一个独立告警实例。钉钉、企业微信、飞书、邮件、Webhook 这些都是以插件形式预置好的你只需要在 UI 上创建实例、填参数、保存然后把它挂到告警组里剩下的交给 AlertServer 去处理。全程不用动一行 conf 文件也不需要因为改告警配置去重启服务。这里我整理了一下几个大版本的对比给同样有“旧经验”的读者作个参考版本告警配置方式钉钉支持程度我当时的感受1.x修改 alert.properties 后重启服务手动启用参数隐蔽每次改配置都要心惊胆战重启容易影响正在跑的实例2.0.x告警插件化UI 配置已支持钉钉自定义机器人Webhook 和关键词填好基本就能用开始顺手了3.x告警实例 告警组分离管理支持关键词、加签、指定人配置路径变了但灵活性高了值得重新学一遍所以我给所有“再次使用”海豚调度器的朋友一个建议先别急着凭肌肉记忆操作登录 UI 后先去“安全中心”里转一圈看看当前版本的告警入口在哪里。老经验可以用来理解底层逻辑但具体操作一定要以当前版本的界面为准。1.2 钉钉告警链路里到底有哪些角色配置钉钉告警之前先把这条链路搞清楚后面排查问题才能有的放矢。DolphinScheduler 的告警机制可以拆成三段第一段是触发侧。工作流或任务节点执行完MasterServer 会根据工作流定义里配的“通知策略”判断这次运行结果要不要发告警。如果判定需要告警它不会直接去调钉钉接口而是把一条告警事件写入元数据库的告警表t_ds_alert记录里包含项目、工作流、任务节点、运行状态、告警内容这些信息。第二段是传输侧。AlertServer 是独立的告警服务它像一个巡逻员定时去扫描告警表里还没发送的记录根据告警实例对应的插件类型把消息格式化成钉钉能识别的 JSON然后调用钉钉自定义机器人的 Webhook 地址把消息推出去。第三段是接收侧。钉钉群里的自定义机器人收到 HTTP 请求后先做安全校验。如果你开启了自定义关键词它要检查消息里有没有包含这个词如果开启了加签它要验证 URL 上的签名是否合法。校验通过消息才会出现在群里。这个机制很像小区物业的巡更流程。安保发现楼道灯坏了先在值班本上记一笔巡更员定时翻值班本拿到记录后打电话通知维修师傅。任何一个环节断了告警就送不到钉钉。最典型的三种情况安保根本没写值班本通知策略没选对、巡更员在偷懒AlertServer 没启动、维修师傅不接电话钉钉机器人安全校验没过。后面排查问题的时候我基本就是按这三段来看的。2. 动手前准备钉钉机器人、Webhook 与安全参数2.1 在钉钉里创建一个告警群并添加自定义机器人配置 DolphinScheduler 之前先把钉钉这一侧的“接收端”准备好。我建议单独建一个告警群不要往大群里发因为调度告警可能比较频繁容易打扰到不相关的人。群里一般拉数据开发、运维、以及对这个任务产出有直接诉求的业务同学就够了。建群之后进入群设置找到“智能群助手”选择“添加机器人”再选“自定义机器人”。机器人名字可以叫 dolphinscheduler-alert方便一眼看出是哪个系统发的。创建时记得做好安全设置钉钉给了三种选项自定义关键词要求消息内容里必须包含你设置的词否则拒绝发送。比如你设了“DolphinScheduler”那么每一条消息正文里都得有这几个字。好处是简单坏处是如果你后来又自定义了消息模板模板里没带关键词消息就发不出去。加签钉钉会在发送请求时校验 URL 上的动态签名。DolphinScheduler 的钉钉插件原生支持加签只需要把密钥填到 Secret 字段里就行。这是我最推荐的一种方式对消息内容没有额外限制安全性也更高。IP 地址段只允许从指定出口 IP 发起请求。如果你们公司有固定的公网出口这个也可以开但如果 DolphinScheduler 部署在容器环境、出口 IP 经常变就别选这个了。三种方式可以多选但多选时约束会叠加以后排查问题会多一层变量。我自己的经验是生产环境只开“加签”一种最省心。如果你用的是旧版本或者不想折腾加签那就用自定义关键词并且保证告警内容里永远带这个关键词。2.2 保存 Webhook 和关键参数机器人创建成功之后钉钉会给你一个 Webhook 地址格式大概是这样https://oapi.dingtalk.com/robot/send?access_token这里是一长串tokenaccess_token 就是机器人的身份凭证相当于这群聊的“门禁卡”。这个地址不要贴到公开仓库或文档里任何人都可以用它往群里发消息。如果开了加签还会看到一个以 SEC 开头的密钥这个就是 Secret待会儿要填进 DolphinScheduler 的告警实例里。如果你希望告警时能 群里的特定成员提前把他们的钉钉手机号准备好后面配置时填到“指定用户”字段里。这里不建议每个人都 只 关键负责人就行不然告警一多大家容易麻木。2.3 确认 AlertServer 服务在跑有几类部署方式对应 AlertServer 的启动和检查方法不太一样二进制部署的话在 DolphinScheduler 安装目录下执行bin/dolphinscheduler-daemon.sh start alert-server启动然后可以用jps看进程会看到一个名字里带 AlertServer 的 Java 进程。Docker Compose 部署的话docker-compose 配置文件里会有一个 alert-server 服务用docker compose ps查看状态用docker compose logs alert-server看日志。Kubernetes 部署的话对应的是一个 Deployment用kubectl get pods确认状态。这个检查很关键。我遇到过不少次告警配置全对但就是收不到消息最后发现是部署时只起了 MasterServer 和 WorkerServerAlertServer 压根没启动。它没启动的后果是任务失败后告警记录会一直堆积在 t_ds_alert 表里状态一直停留在 0等待发送钉钉自然什么都收不到。3. 核心实操在 DolphinScheduler 里一步步添加钉钉告警3.1 新建告警实例Webhook、Secret、指定成员逐个填配置入口在 UI 的“安全中心”模块注意需要管理员账号才能操作。路径是安全中心 - 告警实例管理 - 创建告警实例。点开之后告警插件选择“钉钉”然后会出现一堆字段我逐个说一下填什么。字段填什么说明告警插件钉钉3.x 里内置的插件类型实例名称例如“生产-钉钉运维群”建议带上环境标识避免测试环境告警混进生产群Webhookhttps://oapi.dingtalk.com/robot/send?access_tokenxxx从钉钉机器人页面复制整串粘贴关键字例如“DolphinScheduler”如果钉钉机器人开了“自定义关键词”才需要填与钉钉侧保持一致SecretSECxxxxxxxx如果钉钉机器人开了“加签”把密钥粘过来不需要自己算签名插件内部会处理是否 所有人是/否看告警群的诉求核心系统故障可以开指定用户手机号用逗号分隔不 所有人时可以只 某几个人保存的时候如果提示参数校验失败多半是 Webhook 格式不对或者 Secret 复制的时候没复制全。另外实例名称里的环境信息很重要我曾经吃过亏测试环境的告警实例和生产环境混在一起测试任务失败时生产群里响成一片后来所有告警实例都强制带上前缀这种情况才彻底解决。3.2 创建告警组把告警实例和业务解耦告警实例建好之后接下来要去“安全中心 - 告警组管理”里创建一个告警组。比如叫“数据研发告警组”然后在“选择告警实例”里把刚才建好的钉钉告警实例勾选上。多这一层有什么好处最直接的好处是解耦。告警组面向业务告警实例面向通道。业务方创建工作时不用关心这个组背后是钉钉还是邮件它只要选中“数据研发告警组”就代表这个工作流的失败通知会发到对应的人那里。将来运维想换机器人、换钉钉群只需要改告警实例不需要去翻每一个工作流定义。在团队协作的时候这种分层设计能省掉大量沟通成本。创建告警组之后可以顺便检查一下项目维度。DolphinScheduler 里不同的项目可以配置不同的告警组如果你们有多个项目共用一套调度平台建议按项目把告警组分开避免 A 项目的任务失败把 B 项目的人半夜吵醒。3.3 工作流里开启通知不选“通知策略”等于白配这是新手最容易漏的一步。很多人以为建好告警实例、告警组任务失败就会自动发钉钉其实不是。你还要在工作流这一侧打开“通知”的开关。有两个地方要设置第一个是工作流定义。编辑工作流时DAG 画布右侧有“工作流属性”面板里面有一个“告警组”下拉框要在这里把刚才创建的告警组选上。如果不选这个工作流跟任何告警通道都是断开的。第二个是运行或定时调度时的“通知策略”。在 DolphinScheduler 3.x 里手动点击“运行”启动工作流时弹窗里会有“失败策略”和“通知策略”两个选项。通知策略有四种都不发、成功发、失败发、成功和失败都发。如果你希望任务失败时收到钉钉消息就选“失败发”如果成功也想知道就选“成功和失败都发”。配置定时调度的时候也一样。在“定时管理”里编辑定时任务时同样能看到通知策略的选项而且这里更关键因为定时任务一旦跑起来你不可能每天都守在屏幕前看结果靠的就是这个通知策略。我见过一个比较典型的误操作告警实例、告警组全都配置正确工作流属性里的告警组也选了但定时调度创建的时候通知策略默认是“都不发”结果任务连续失败三天钉钉一条消息都没收到。所以配置完一定要回头检查通知策略这个是整个链路里“最后一公里”的开关。3.4 验证告警故意让任务失败一次配置完之后强烈建议做一个主动验证不要等真实任务失败了才发现问题。验证方式很简单在工作流定义里新建一个测试工作流加一个 Shell 节点节点内容写exit 1然后在“运行”弹窗里通知策略选择“失败发”启动工作流。任务失败后先看一眼钉钉群有没有收到消息。如果收到了说明整条链路是通的后面把测试工作流删掉或停掉就行。如果没收到马上去查元数据库执行SELECT id, title, content, alert_status, log, create_time FROM t_ds_alert ORDER BY id DESC LIMIT 5;这里会看到最近几条告警记录重点关注 alert_status 字段0 表示等待发送说明告警事件已经写入但 AlertServer 还没处理先检查它有没有启动。1 表示发送成功说明 AlertServer 已经调用了钉钉接口但钉钉没收到问题大概率在钉钉机器人安全设置或 Webhook 地址上。这时候看 log 字段里面会记录钉钉接口返回的内容。2 表示发送失败log 字段一般会写明失败原因比如超时、签名不对、消息格式不对等。这一步就是前面说的三段式排查思路先确认触发侧有没有写值班本再确认巡更员有没有干活最后确认维修师傅接没接电话。4. 让钉钉预警真正“好用”的几个细节4.1 默认告警消息长什么样够用吗DolphinScheduler 通过内置钉钉插件发出来的消息大致包含项目名、工作流名、任务节点名、执行时间、运行状态、日志地址等信息。对于大多数场景这个默认内容底子是够用的。它至少能告诉你“哪个工作流的哪个节点挂了”有了这条信息登进调度平台去看具体日志通常也不难。但它的短板也很明显。第一消息里不会直接告诉你这个任务重试过几次。如果任务因为上游临时抖动失败过一次、重试后成功了你看到的是一条失败消息但实际任务已经恢复了容易让人虚惊一场。第二日志地址如果部署环境没配好默认可能是容器内网地址你在办公网络下点开就是个连接超时。第三拆链路排查的时候默认消息不会带工作流实例 ID你要在平台上翻半天才能定位到具体哪次运行出问题。所以我的建议是默认告警拿来当兜底没问题但如果你们团队对告警质量有要求比如“一条消息能判断要不要立刻爬起来处理”那就得在消息内容上做文章。4.2 用 Shell/Python 节点直发自定义钉钉消息DolphinScheduler 内置的钉钉插件消息格式是固定的想完全自定义最简单的方式不是去改插件源码而是直接在任务节点里发起 HTTP 调用自己拼消息体给钉钉机器人。如果你的钉钉机器人只开了“自定义关键词”安全设置方案很简单。加一个 Python 节点或 Shell 节点用 requests 或 curl 直接发 Webhook 请求JSON 里带上关键词就行。示例import requests import json webhook https://oapi.dingtalk.com/robot/send?access_tokenxxx data { msgtype: markdown, markdown: { title: 数据任务失败, text: ### 任务失败\\n - 项目: demo\\n - 工作流: data_daily_summary\\n - 错误码: E_0021\\n - 建议: 检查上游表是否就绪 }, at: { isAtAll: False, atMobiles: [13800000000] } } resp requests.post(webhook, jsondata) print(resp.text)如果你的机器人开了“加签”那就麻烦一点因为签名是根据当前时间戳动态计算的。在 Python 节点里可以这样算import time import hmac import hashlib import base64 import urllib.parse import requests import json secret SEC你的密钥 timestamp str(round(time.time() * 1000)) string_to_sign f{timestamp}\\n{secret} hmac_code hmac.new(secret.encode(utf-8), string_to_sign.encode(utf-8), digestmodhashlib.sha256).digest() sign urllib.parse.quote_plus(base64.b64encode(hmac_code)) webhook fhttps://oapi.dingtalk.com/robot/send?access_tokenxxxtimestamp{timestamp}sign{sign} data { msgtype: text, text: {content: 自定义告警内容带关键词也没问题}, } resp requests.post(webhook, jsondata) print(resp.text)这里有一个重要提醒DolphinScheduler 的 HTTP 任务节点只能填静态 URL没法在请求时动态计算签名所以如果机器人开了加签直接用 HTTP 任务节点发送一定会因为缺少签名或签名不合法而失败。要么用 Shell/Python 节点自己写逻辑要么就把机器人安全设置改成“自定义关键词”。这是我踩过的一个很具体的坑分享出来给你们避一下。4.3 告警分级失败、超时、成功分别怎么发告警平台最怕的不是没告警而是告警轰炸。任务一失败就发、一个小抖动就发群里天天狼来了真出大事的时候反而没人看了。我现在的做法是分三级控制。第一级任务失败重试。DolphinScheduler 的任务节点高级参数里有“失败重试次数”和“失败重试间隔”。对于非核心依赖的上游任务我会把重试次数设成 2 次间隔 5 分钟。临时性的资源不足、网络抖动这类问题重试一次往往就恢复的没必要一失败就立刻打扰人。重试仍然失败的才值得一条钉钉消息。第二级超时告警。任务卡死但不报错是另一种很难受的情况。比如一个数据同步任务因为数据库连接池被占满挂着不走失败策略不会触发但任务实际上已经没有产出了。DolphinScheduler 任务节点里可以开“超时告警”设置一个超时时间。时间怎么定我一般按这个任务正常耗时的 1.5 倍再留 30 分钟余量来设置。比如平时跑 20 分钟我就设 60 分钟给它充足的容忍度但真卡死了 60 分钟一定会触发超时告警。第三级成功告警只给核心链路开。日报类、对账类、面向领导看板的任务跑完发一条成功消息大家图个安心。但非核心 ETL 任务别开成功告警一天几十个任务全发成功通知很快就会被群消息淹没了。5. 踩坑实录钉钉告警常见问题与排查5.1 常见问题速查表为了方便读者直接对号入座我把这次实际踩过、以及周边同事反复问过的问题整理成一张表现象可能原因解决办法钉钉收不到消息数据库 alert_status 1钉钉机器人安全校验失败或 Webhook 地址错误看 t_ds_alert.log 字段里钉钉接口返回的内容确认关键词、加签是否匹配钉钉收不到消息数据库 alert_status 2AlertServer 发送异常如 URL 不可达、连接超时查看 alert-server.log检查网络能否访问 oapi.dingtalk.com数据库 alert_status 0一直不发AlertServer 没启动或线程池阻塞确认进程存在必要时重启 alert-server告警时间比本地时间晚 8 小时服务器或容器时区是 UTC二进制部署设TZAsia/Shanghai容器部署在 compose 里加时区环境变量告警消息里没有 指定的人告警实例里“是否 所有人”或“指定用户”没保存成功重新打开告警实例确认下拉值和手机号都回显正常任务失败但一条告警都没有工作流属性里没选告警组或通知策略为“都不发”在工作流属性绑定告警组运行/定时时把通知策略改为“失败发”Server 日志报 TLS/SSL 握手失败JVM 与钉钉服务端 TLS 版本不兼容在启动参数里加-Dhttps.protocolsTLSv1.2重启告警服务5.2 典型案例自定义关键词不匹配导致消息被拒有一次我给一个任务配置好了钉钉告警数据库里显示发送成功但群里就是没消息。我看了 t_ds_alert 的 log 字段里面有钉钉返回的errcode和errmsg明确指出消息内容不包含关键词。原因很有意思钉钉机器人创建的时候同事顺手填了一个自定义关键词但他没告诉任何人DolphinScheduler 告警实例里也填了相同的关键词按理说应该能过。可是告警消息内容在某些异常场景下可能不包含这个关键词结果被钉钉拒之门外。排查思路就是去钉钉后台看机器人的安全设置确认关键词配置然后对比告警实例里填的关键字和实际发送的消息内容。如果消息是动态拼接的干脆把关键词设成一个一定会出现的固定字符比如项目前缀或者改用加签方式。5.3 典型案例容器时区问题导致告警时间错乱还有一个容易被忽略的问题Docker 部署的 DolphinScheduler默认镜像时区是 UTC告警消息里的执行时间会比北京时间晚 8 个小时。一开始我还以为是代码 bug后来把 alert-server 的日志打印时间戳和数据库插入时间对比了一下发现是时区问题。解决办法不复杂。Docker Compose 部署时在相关服务的环境变量里加上environment: - TZAsia/Shanghai同时可以考虑把宿主机的 /etc/timezone 和 /etc/localtime 挂载进容器。如果你使用的是高版本基础镜像TZ 环境变量基本就能解决。改完之后重启 alert-server 和 api-server让整个链路的时间口径统一。5.4 案例复盘生产环境重启后告警实例丢失有一次在测试环境手动部署了一套 DolphinScheduler配完钉钉告警当天一切正常第二天重启容器后进 UI 发现告警实例全没了。查了一圈问题出在网上找的一个 docker-compose 模板把元数据库配置成了默认的 H2 内存库容器一重启数据全清空。生产环境或者任何需要长期运行的测试环境都得把元数据库切到外部 MySQL并且把 MySQL 的存储卷持久化。否则不只是告警实例你所有的工作流定义、调度计划都会跟着没。在 DolphinScheduler 的 conf/application.yaml 里把 spring.datasource 配置指向外部 MySQL并且数据库用 utf8mb4 字符集。配置完之后重启 api-server再用 UI 操作一遍确认配置没问题然后把数据目录持久化到宿主机或云盘。这一步看着基础但真出了事故才后悔就晚了。最后再说两句把钉钉告警从“配通”到“配好用”中间差的那一步往往是告警内容的打磨和发送噪音的控制。我现在的习惯是核心工作流失败告警加上最多一次重试后才发每个告警实例的名字带环境标识测试环境的告警绝不和生产群混在一起每周翻一眼告警表看哪些工作流在重复失败却没什么人响应这种记录反过来能推动业务方把 SLA 定下来。这套做法其实不复杂但比单纯拿到一个能用的 Webhook 价值大得多。如果你也刚接手一套 DolphinScheduler建议先把告警跑通再照这个思路慢慢调。祝你的任务一次跑成功。