前言

在 Apache DolphinScheduler(以下简称「海豚调度」)里配置工作流时,全局参数是最常用的传参方式之一:在流程定义里设好 biz_typeregion 等默认值,任务脚本里用 ${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 类型)执行:

1
python3 /data/scripts/flow_1.py ${biz_type} ${region}

工作流全局参数(流程定义里保存):

参数 默认值
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 Contentorder111 cn-north333
定时调度 失败,脚本变为 python3 /data/scripts/flow_1.py(无参数)

任务日志报错:

1
参数不足,需要 biz_type region,实际: ['/data/scripts/flow_1.py']

1.3 初步怀疑(均被排除)

排查初期,我按社区常见说法逐一验证:

  1. 定时绑定旧版本工作流 —— 已全下线、重保存、重建定时,版本号已升到 v14,问题依旧。
  2. global_params JSON 缺字段 —— 数据库里格式完整,含 direct: INtype: VARCHAR
  3. 全局参数只写在运行弹窗 —— 已确认写在流程定义中,且实例级 global_params 有值。

说明问题不在「参数没存进去」,而在参数从实例到任务的合并/替换环节


2. 分析过程

2.1 第一步:查 MySQL 元数据

DolphinScheduler 3.4 将表名从 process_* 改为 workflow_*,查库时注意表名。

工作流定义t_ds_workflow_definition):

1
2
3
4
[
  {"prop":"biz_type","value":"order000","direct":"IN","type":"VARCHAR"},
  {"prop":"region","value":"cn-north333","direct":"IN","type":"VARCHAR"}
]

定时实例t_ds_workflow_instance,command_type=6 即 SCHEDULER):

  • global_params:同上,有值
  • command_param"commandParams": null

结论:实例层全局参数正常,不是 DB 存储问题。

2.2 第二步:对比任务日志

定时实例 task 40 的 Worker 日志关键片段:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
Initialize shell task params {
  "localParams": [
    {"prop":"biz_type", "direct":"IN", "value":""},
    {"prop":"region",   "direct":"IN", "value":""}
  ],
  "rawScript": "python3 /data/scripts/flow_1.py ${biz_type} ${region}"
}
Set taskVarPool: null successfully
Final Script Content:
python3 /data/scripts/flow_1.py

全局参数在上下文里存在,但合并进脚本前被清空

2.3 第三步:对比手动 vs 定时的 Master 日志

这是整个排查的转折点。在 dolphinscheduler-standalone.log 里搜索 prepareParamsMap

手动运行(成功)scheduleTime=0

1
2
3
4
5
6
commandParam: "commandParams": [
  {"prop":"biz_type","value":"order111"},
  {"prop":"region","value":"cn-north333"}
]
prepareParamsMap: biz_type=order111, region=cn-north333
Final Script: python3 /data/scripts/flow_1.py order111 cn-north333

定时调度(失败)scheduleTime≠0

1
2
3
4
commandParam: "commandParams": null
globalParams: [{"prop":"biz_type","value":"order000"}, ...]
prepareParamsMap: biz_type=(空), region=(空)
Final Script: python3 /data/scripts/flow_1.py

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 海豚调度的参数优先级

官方文档定义的优先级(高 → 低):

1
启动参数 > 本地参数 > 上游参数(VarPool)> 全局参数 > 项目参数

3.2 手动为什么能跑

点击「运行」时,UI 会把工作流全局参数的默认值复制进启动参数commandParams),写入 command_param

1
2
3
4
5
6
7
{
  "commandType": "START_PROCESS",
  "commandParams": [
    {"prop":"biz_type","value":"order111"},
    {"prop":"region","value":"cn-north333"}
  ]
}

启动参数优先级最高,覆盖了任务里值为空的本地 IN 参数,所以 ${biz_type} 能正确替换。

3.3 定时为什么失败

定时触发时 Master 生成的命令:

1
2
3
4
{
  "commandType": "SCHEDULER",
  "commandParams": null
}

没有启动参数这一层。此时任务本地 IN 里同名且值为空biz_typeregion 会按优先级压过全局参数,最终 prepareParamsMap 里这两个键为空,脚本替换结果为空字符串。

用一张图概括:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
                    ┌─────────────────────────────────────┐
                    │         工作流全局参数               │
                    │  biz_type=order000  region=cn-north │
                    └─────────────────┬───────────────────┘
          ┌───────────────────────────┼───────────────────────────┐
          │                           │                           │
   手动运行 │                    定时调度 │                           │
          ▼                           ▼                           │
  commandParams               commandParams=null                   │
  (启动参数,最高优先级)              │                           │
          │                           │                           │
          ▼                           ▼                           │
  覆盖空的本地 IN  ──────────►  本地 IN(空) 覆盖全局  ◄─────────────┘
          │                           │
          ▼                           ▼
  脚本: ... order111 cn-north    脚本: ... (无参数)
          │                           │
          ▼                           ▼
        成功                         失败

3.4 为什么下线重保存无效

配置冲突一直存在:全局参数与本地 IN 同名。手动跑时靠启动参数「兜底」,定时没有这层,所以不是版本或上线流程的问题,而是参数模型使用不当。


4. 解决方案

4.1 方案 A(推荐):删除与全局同名的本地 IN 参数

任务1 的「自定义参数」中:

操作 参数
删除 biz_type(IN)
删除 region(IN)
保留 user_name、order_id、biz_date(OUT,供下游 task_b 使用)

Shell 脚本不用改

1
python3 /data/scripts/flow_1.py ${biz_type} ${region}

${biz_type}${region} 将直接从全局参数替换,不再被空的本地 IN 覆盖。

验证:等下一次定时触发,日志中应出现:

1
python3 /data/scripts/flow_1.py order000 cn-north333

4.2 方案 B:本地 IN 写死默认值

1
2
biz_type  IN  VARCHAR  order000
region    IN  VARCHAR  cn-north333

能跑,但与全局参数重复维护,改一处要记得改另一处,不推荐。

4.3 方案 C:Shell 兜底(临时)

1
python3 /data/scripts/flow_1.py ${biz_type:-order000} ${region:-cn-north333}

适合短期保定时可用,不解决参数模型本身的问题。

4.4 对 task_b / task_c 的说明

  • task_btask_c 的 IN 参数(user_nameorder_id 等)来自上游 OUT,必须保留本地 IN(空值接收 VarPool),这与 task_a 的场景不同。
  • 规则:纯全局入参不要在任务里再声明同名本地 IN;上游传参才需要本地 IN。

5. 排查命令备忘

以下命令在排查时反复用到,整理备查。

查工作流全局参数:

1
2
mysql -uroot -p dolphinscheduler -e \
  "SELECT code,name,version,global_params FROM t_ds_workflow_definition WHERE name='flow_1_demo';"

对比实例级参数:

1
2
mysql -uroot -p dolphinscheduler -e \
  "SELECT id,command_type,command_param,global_params FROM t_ds_workflow_instance ORDER BY id DESC LIMIT 5;"

在 Master 日志中找参数合并结果:

1
2
grep 'prepareParamsMap' /path/to/dolphinscheduler-standalone.log | tail -5
grep 'Success bootstrap command' /path/to/dolphinscheduler-standalone.log | tail -3

看任务最终脚本:

1
grep -A6 'Final Script Content' /path/to/task/instance.log

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