前言
在 Apache DolphinScheduler(以下简称「海豚调度」)里配置工作流时,全局参数是最常用的传参方式之一:在流程定义里设好 biz_type、region 等默认值,任务脚本里用 ${biz_type} 引用,手动点「运行」一切正常——直到挂上 Cron 定时,脚本里的参数突然全部变成空字符串,任务 exit 1。
这个问题我踩了完整一遍:下线重保存、重建定时、核对全局参数格式……都试过了,依然失败。本文把现象、排查路径、日志证据、根因结论和修复方案整理成一篇可复用的排查笔记,环境为 DolphinScheduler 3.4.2 Standalone + MySQL 元数据库。
1. 背景与现象
1.1 工作流设计
demo 项目中的工作流 flow_1_demo,三任务链 task_a → task_b → task_c,脚本在服务器 /data/scripts/。
第一个任务 任务1(SHELL 类型)执行:
|
|
工作流全局参数(流程定义里保存):
| 参数 | 默认值 |
|---|---|
| biz_type | order000 |
| region | cn-north333 |
任务自定义参数(本地 IN):
| 参数 | 方向 | 值 |
|---|---|---|
| biz_type | IN | (空) |
| region | IN | (空) |
| user_name | OUT | (空) |
| order_id | OUT | (空) |
| biz_date | OUT | (空) |
定时 Cron:0 0/3 * * * ? *(每 3 分钟)。
1.2 故障表现
| 触发方式 | 结果 |
|---|---|
| 手动运行 | 成功,Final Script Content 含 order111 cn-north333 |
| 定时调度 | 失败,脚本变为 python3 /data/scripts/flow_1.py(无参数) |
任务日志报错:
|
|
1.3 初步怀疑(均被排除)
排查初期,我按社区常见说法逐一验证:
- 定时绑定旧版本工作流 —— 已全下线、重保存、重建定时,版本号已升到 v14,问题依旧。
- global_params JSON 缺字段 —— 数据库里格式完整,含
direct: IN和type: VARCHAR。 - 全局参数只写在运行弹窗 —— 已确认写在流程定义中,且实例级
global_params有值。
说明问题不在「参数没存进去」,而在参数从实例到任务的合并/替换环节。
2. 分析过程
2.1 第一步:查 MySQL 元数据
DolphinScheduler 3.4 将表名从
process_*改为workflow_*,查库时注意表名。
工作流定义(t_ds_workflow_definition):
|
|
定时实例(t_ds_workflow_instance,command_type=6 即 SCHEDULER):
global_params:同上,有值command_param:"commandParams": null
结论:实例层全局参数正常,不是 DB 存储问题。
2.2 第二步:对比任务日志
定时实例 task 40 的 Worker 日志关键片段:
|
|
全局参数在上下文里存在,但合并进脚本前被清空。
2.3 第三步:对比手动 vs 定时的 Master 日志
这是整个排查的转折点。在 dolphinscheduler-standalone.log 里搜索 prepareParamsMap:
手动运行(成功) — scheduleTime=0:
|
|
定时调度(失败) — scheduleTime≠0:
|
|
2.4 第四步:发现「hello」对照组
工作流里还有一个仅存在于全局参数、未在任务本地声明的参数 hello:
| 参数 | 全局 | 任务本地 IN | 手动 | 定时 |
|---|---|---|---|---|
| hello | 123 | 无 | 123 | 123 |
| biz_type | order000 | 空 IN | order111 | 空 |
| region | cn-north333 | 空 IN | cn-north333 | 空 |
规律非常清晰:
- 只有全局、没有本地 IN 同名参数 → 手动和定时都正常。
- 全局与本地 IN 同名 → 手动正常、定时失败。
3. 根因结论
3.1 海豚调度的参数优先级
官方文档定义的优先级(高 → 低):
|
|
3.2 手动为什么能跑
点击「运行」时,UI 会把工作流全局参数的默认值复制进启动参数(commandParams),写入 command_param:
|
|
启动参数优先级最高,覆盖了任务里值为空的本地 IN 参数,所以 ${biz_type} 能正确替换。
3.3 定时为什么失败
定时触发时 Master 生成的命令:
|
|
没有启动参数这一层。此时任务本地 IN 里同名且值为空的 biz_type、region 会按优先级压过全局参数,最终 prepareParamsMap 里这两个键为空,脚本替换结果为空字符串。
用一张图概括:
|
|
3.4 为什么下线重保存无效
配置冲突一直存在:全局参数与本地 IN 同名。手动跑时靠启动参数「兜底」,定时没有这层,所以不是版本或上线流程的问题,而是参数模型使用不当。
4. 解决方案
4.1 方案 A(推荐):删除与全局同名的本地 IN 参数
在 任务1 的「自定义参数」中:
| 操作 | 参数 |
|---|---|
| 删除 | biz_type(IN) |
| 删除 | region(IN) |
| 保留 | user_name、order_id、biz_date(OUT,供下游 task_b 使用) |
Shell 脚本不用改:
|
|
${biz_type}、${region} 将直接从全局参数替换,不再被空的本地 IN 覆盖。
验证:等下一次定时触发,日志中应出现:
|
|
4.2 方案 B:本地 IN 写死默认值
|
|
能跑,但与全局参数重复维护,改一处要记得改另一处,不推荐。
4.3 方案 C:Shell 兜底(临时)
|
|
适合短期保定时可用,不解决参数模型本身的问题。
4.4 对 task_b / task_c 的说明
task_b、task_c的 IN 参数(user_name、order_id等)来自上游 OUT,必须保留本地 IN(空值接收 VarPool),这与 task_a 的场景不同。- 规则:纯全局入参不要在任务里再声明同名本地 IN;上游传参才需要本地 IN。
5. 排查命令备忘
以下命令在排查时反复用到,整理备查。
查工作流全局参数:
|
|
对比实例级参数:
|
|
在 Master 日志中找参数合并结果:
|
|
看任务最终脚本:
|
|
6. 经验总结
| 教训 | 说明 |
|---|---|
| 手动能跑 ≠ 定时能跑 | 手动会注入 commandParams,定时没有 |
看日志要看到 prepareParamsMap |
全局参数有值不代表任务层合并成功 |
| 本地 IN 空值不是「占位符」 | 在定时场景下会按优先级压过全局参数 |
| DS 3.4 表名已变 | t_ds_workflow_definition / t_ds_workflow_instance |
| 同名参数是最隐蔽的坑 | 仅全局存在的参数(如 hello)可作为对照组 |
如果你也在海豚调度里遇到「全局参数定时为空、手动正常」,优先检查:任务自定义参数里是否与全局参数同名且值为空。删掉多余的本地 IN,往往比反复下线/上线更有效。
附录:环境信息
| 项 | 值 |
|---|---|
| DolphinScheduler | 3.4.2 Standalone |
| 元数据库 | MySQL 8.0 |
| 任务类型 | SHELL(跑外部 .py 脚本) |
| 操作系统 | AlmaLinux 9.2 |