轻流:用 YAML 风格文本表达串行/并行流程
轻流:用 YAML 风格文本表达串行/并行流程
为什么需要“轻流”?
在日常开发中,我们经常需要描述一段执行顺序明确、结构简单的流程:
“先校验权限,然后并行下载文件和加载配置,接着处理数据,最后同时写入结果并上报指标。”
这类逻辑通常出现在自动化脚本、服务编排、CI/CD 步骤或内部工具中。但若为此引入 BPMN 图形建模,成本过高;若仅用代码硬编码,又难以配置化与可视化。
“轻流”应运而生:它用 YAML 风格的纯文本,仅通过 series(串行)和 parallel(并行)两个关键字,清晰表达上述流程——无需图形、无需复杂语法,一行配置即是一张流程图。
直观效果示例(带注释)
series: # 整个流程是串行执行(从上到下)
- check_permission # 第1步:校验权限(单任务)
- parallel: # 第2步:并行执行以下两个子任务(同时开始)
- download_source # ↳ 子任务A:下载源文件
- load_config # ↳ 子任务B:加载配置
- transform_data # 第3步:转换数据(等并行任务全部完成后执行)
- parallel: # 第4步:再次并行执行输出与监控
- write_output # ↳ 子任务A:写入输出文件
- emit_metrics # ↳ 子任务B:上报指标
✅ 一眼看懂:
- 缩进层级 = 执行层级
series下的任务按顺序执行parallel下的任务并发执行- 并行块整体视为“一个步骤”,完成后才进入下一步
1. 文本流程语法(YAML 风格 / 格式化的 json )
使用 series 和 parallel 关键字 + 子节点数组定义流程结构。
- 叶子节点:字符串(任务标识)
- 具体放什么内容,可视情况需要来定
- 比如:前期交流表达流程时,就可以是很宽松的文本
- 比如:想要表达更格式化的信息,可以 $id:$name:$desc
- 容器节点:含
series或parallel字段的对象,值为子节点列表 - 支持任意层级嵌套
示例
简单串行
series:
- validate # 第一步
- process # 第二步(validate 完成后执行)
- save # 第三步(process 完成后执行)
并行执行
parallel:
- send_email # 三个任务同时开始
- update_cache
- log_event
嵌套混合
series:
- auth # 先认证
- parallel: # 再并行获取用户和角色信息
- fetch_user
- fetch_role
- render # 等两者都完成后渲染页面
2. Java 模型定义(其它类似)
所有节点统一实现空标记接口 TxtNode,明确其“流程节点”职责。
// 标记接口:所有流程节点必须实现
public interface TxtNode {}
叶子节点(原子任务)
public record TxtTask(String name) implements TxtNode {}
// 可扩展业务特定叶子节点,如:
// public record TxtApiCall(String endpoint) implements TxtNode {}
容器节点(组合结构)
public record TxtSeries(List<TxtNode> steps) implements TxtNode {}
public record TxtParallel(List<TxtNode> branches) implements TxtNode {}
所有流程均由
TxtNode构成,支持统一递归处理。
3. 模型 ↔ 文本转换
3.1 模型 → YAML(序列化)
public class FlowYamlWriter {
public static String toYaml(TxtNode node) {
if (node instanceof TxtTask task) {
return task.name();
} else if (node instanceof TxtSeries series) {
return "series:\n" + indentList(series.steps());
} else if (node instanceof TxtParallel parallel) {
return "parallel:\n" + indentList(parallel.branches());
}
throw new IllegalArgumentException("Unsupported node: " + node);
}
private static String indentList(List<TxtNode> nodes) {
return nodes.stream()
.map(n -> "- " + toYaml(n).replace("\n", "\n "))
.collect(Collectors.joining("\n "));
}
}
3.2 YAML → 模型(解析)
依赖 SnakeYAML:
public class FlowYamlReader {
public static TxtNode fromYaml(String yaml) {
Yaml parser = new Yaml();
Object obj = parser.load(yaml);
return parseNode(obj);
}
@SuppressWarnings("unchecked")
private static TxtNode parseNode(Object obj) {
if (obj instanceof String str) {
return new TxtTask(str);
} else if (obj instanceof Map map) {
if (map.containsKey("series")) {
List<TxtNode> steps = ((List<?>) map.get("series"))
.stream().map(FlowYamlReader::parseNode)
.toList();
return new TxtSeries(steps);
} else if (map.containsKey("parallel")) {
List<TxtNode> branches = ((List<?>) map.get("parallel"))
.stream().map(FlowYamlReader::parseNode)
.toList();
return new TxtParallel(branches);
}
}
throw new IllegalArgumentException("Invalid node: " + obj);
}
}
4. 与 BPMN 的关系说明
本模型不兼容完整 BPMN。BPMN 是通用工作流标准,而“轻流”仅覆盖其最简子集。
可转换的 BPMN 片段示例
BPMN 中如下结构:
Start → A → [Parallel Gateway] → B & C → [Join Gateway] → D → End
可转换为:
series:
- A # 串行第一步
- parallel: # 并行分支
- B
- C
- D # 串行最后一步(等B、C都完成)
转换限制
- 仅当 BPMN 流程不含条件网关(XOR)、循环、事件、子流程时可转换
- 实际建议:用“轻流”描述主干逻辑,复杂路径仍由 BPMN 或代码处理
5. 适用场景 vs 局限
✅ 推荐使用
- 自动化任务步骤配置(如数据导出、批处理)
- CI/CD 流水线中的线性阶段
- 微服务调用编排(无分支的 Saga 步骤)
- 执行日志中的流程快照
- API 文档中的调用序列说明
❌ 禁止使用
- 含 if/else 判断的业务逻辑
- 需要重试或循环的场景
- 多级审批、加签、退回等人工流程
- 依赖消息触发或定时事件的流程
总结
“轻流”是一种极简、文本优先的流程表达方案:
- 核心结构:仅
series(串行)与parallel(并行) - 文本格式:YAML 风格,可直接嵌入配置
- Java 模型:统一
TxtNode接口,支持TxtTask/TxtSeries/TxtParallel - 能力边界:明确限定于无分支、无循环的简单流程
当你的流程可以用一句话描述清楚执行顺序时,“轻流”就是最佳表达方式。若需更复杂控制流,请回归代码或 BPMN——简单问题,简单解法。

浙公网安备 33010602011771号