Solon v3.8.0

graph - 高级节点模式(网关)

</> markdown
2026年1月5日 上午10:53:09

1、什么是网关(Gateway)?

在 Solon-Flow 的世界观里,节点分为活动节点(Activity)和网关节点(Gateway)。

  • 执行节点:负责“干活”(执行具体的 Task)。
  • 网关节点:可以“干活”,还可以负责“调度”(决定流向、等待分支、循环数据)。

2、四大常用网关再对比一下

(在 Solon Flow 开发,节点类型处有介绍)通过下表,你可以快速决定在业务中使用哪种网关:

网关类型逻辑特征现实类比适用场景举例
EXCLUSIVE (排他)多个分支只走其一单选题根据金额选择审批人。
INCLUSIVE (包容)满足条件的全部都走多选题满足“金额大”且“有风险”时,同时触发两个预警。
PARALLEL (并行)全部都走全选题同时调用三方支付、短信、库存接口。
LOOP (循环)按集合数据循环往复传送带批量给一组用户发通知。

3、高级实战:并行与聚合 (Parallel & Join)

这是提升系统吞吐量的“杀手锏”。利用并行网关,你可以让原本串行的任务在多个线程中同时运行。

场景:多源风控校验 我们需要同时调用三个风控引擎,只有全部返回后,流程才能继续。

spec.addParallel("fork_node"); // 开启并发点

spec.addActivity("ali_risk").task("@aliService").linkAdd("join_node");
spec.addActivity("tencent_risk").task("@tenService").linkAdd("join_node");
spec.addActivity("local_risk").task("@localService").linkAdd("join_node");

// 这是一个聚合点,引擎会自动等待上方三个分支全部到达
spec.addParallel("join_node").linkAdd("final_decision");

// 编排连接关系
spec.getNode("fork_node")
    .linkAdd("ali_risk")
    .linkAdd("tencent_risk")
    .linkAdd("local_risk");

底层揭秘:FlowEngine 在执行并行网关时,会尝试获取驱动中的线程池。如果有线程池(通过驱动器配置),它会通过 CountDownLatch 阻塞主链条,直到所有子分支线程执行完毕。

4. 智能编排:循环网关 (Loop)

循环网关通过元数据(Meta)驱动,能够优雅地处理列表遍历。

关键元数据配置:

  • $for:当前循环项存入 Context 的变量名。
  • $in:数据源。可以是 List 变量名,也可以是步进表达式(如 1:10:1)。

示例:批量任务处理

spec.addLoop("loop_start")
    .metaPut("$for", "item")      // 每次循环的对象叫 item
    .metaPut("$in", "dataList")   // 从上下文获取 dataList
    .linkAdd("process_task");

spec.addActivity("process_task").task("@myProcessor").linkAdd("loop_end");

// 结束点,如果不满足退出条件,引擎会根据 loop_stack 自动回流
spec.addLoop("loop_end");

5、避坑指南

为了保证流程的高可用,在使用高级网关时请务必注意:

  • 线程池依赖:并行网关(Parallel)若想实现真正的并发,必须在 FlowDriver 中注入 ExecutorService,否则它会退化为单线程顺序执行。
  • 变量可见性:由于并行分支在不同线程运行,通过 FlowContext.put() 写入变量时要注意并发冲突,尽量在并行结束后再进行结果汇总。
  • 死循环保护:在动态拼装 Loop 逻辑时,建议配合 FlowInvocation 的执行深度限制(depth),防止因为配置错误导致 CPU 飙升。

结语

掌握了高级网关,你便拥有了处理复杂分布式业务的“指挥棒”。Solon-Flow 的强大之处在于,它用最简单的 addNode 语法,封装了复杂的线程同步与状态管理逻辑。