一条命令,十分钟:jeeflow 工作流应用的六语言一键部署

作者:mldong日期:2026/8/26

系列定位:jeeflow 系列第 9 篇(第三季「多语言联邦」第 1 篇)平台:公众号 / 掘金(实用向:一键部署 + 选型)素材版本:引擎 Java 1.8.18 / Go·Python·Node 1.8.20 / PHP 1.3.5 / Rust 1.0.5;一键部署脚本取自 mldong-website前置阅读第 8 篇 · 会签三兄弟:并行/串行/按比例的实现与取舍


一、先上结果

在任意一台装了 Docker 的 Linux 服务器上,执行一条命令:

1curl -fsSL https://www.mldong.com/deploy/mldong-boot3-jeeflow/deploy.sh | bash
2

几分钟后(拉镜像 + 灌种子数据),你会得到一套完整可点的工作流应用:

  • 管理后台前端:登录、用户/角色/部门、字典、流程设计器、发起/审批/会签/抄送全流程
  • 后端 API:jeeflow 工作流引擎接在一个快速开发框架上
  • MySQL:预装好的库,含演示账号和 9 个开箱即用的业务流程(请假、报销、采购、合同审批、用印申请、加班、出差、资产领用、岗位异动),每个流程都带版本历史——改一版定义旧版还在,可追溯可回退
  • 登录superAdmin / 123456

下面四张截图全部来自 Rust 栈——就是刚上线的那条 curl,在一台 2 核 1.7G 的服务器上跑的:

同一台服务器最多可以同时起 8 套,互不冲突。因为这套"一键部署"不是只有一种语言——六语言、八栈,各一条命令:

1curl -fsSL https://www.mldong.com/deploy/mldong-boot4-jeeflow/deploy.sh | bash    # Java · Spring Boot 4(JDK 21)
2curl -fsSL https://www.mldong.com/deploy/mldong-boot3-jeeflow/deploy.sh | bash    # Java · Spring Boot 3(JDK 17)
3curl -fsSL https://www.mldong.com/deploy/mldong-boot2-jeeflow/deploy.sh | bash    # Java · Spring Boot 2(JDK 8)
4curl -fsSL https://www.mldong.com/deploy/mldong-goframe-jeeflow/deploy.sh | bash  # Go · GoFrame
5curl -fsSL https://www.mldong.com/deploy/mldong-nestjs-jeeflow/deploy.sh | bash   # Node.js · NestJS
6curl -fsSL https://www.mldong.com/deploy/mldong-fastapi-jeeflow/deploy.sh | bash  # Python · FastAPI
7curl -fsSL https://www.mldong.com/deploy/mldong-laravel-jeeflow/deploy.sh | bash  # PHP · Laravel
8curl -fsSL https://www.mldong.com/deploy/mldong-salvo-jeeflow/deploy.sh | bash    # Rust · Salvo
9

六语言引擎:Java / Go / Python / Node.js / PHP / Rust。Rust 栈是本周刚上线的——引擎本周在 crates.io 首发(cargo add jeeflow-core@1.0.5),集成仓当天完成验收,一键部署区同步开了 Rust Tab。

你是哪门语言,就选哪条。


二、怎么选?

八栈对比(全部已验证可部署):

语言/框架运行时引擎版本适合
boot4Java · Spring Boot 4JDK 211.8.18新建 Java 项目,要最新框架
boot3Java · Spring Boot 3JDK 171.8.18主流 Java 项目(大多数团队的默认)
boot2Java · Spring Boot 2JDK 81.8.18存量 SB2 / JDK 8 项目(还在 8 上的不少)
goframeGo · GoFrame1.8.20Go 服务、单二进制部署、高并发
nestjsNode.js · NestJS1.8.20全栈 JS 团队、同构/BFF
fastapiPython · FastAPI1.8.20Python 团队、数据/脚本场景
laravelPHP · LaravelPHP 8.41.3.5PHP 存量项目
salvoRust · SalvoRust 1.971.0.5(本周 crates.io 首发)内存安全/高性能诉求,欢迎来踩坑反馈

三个说明:

  1. Java 一个引擎顶三栈:Spring Boot 2/3/4 的框架层不同,底下是同一个 jeeflow-java 引擎,行为一致。选哪个看你 JDK 用哪个。
  2. 各语言引擎版本号不同是正常的:Java/Go/Python/Node 走 1.8.x,PHP 独立里程碑(1.3.x),Rust 新成员从 1.0.x 起步。对齐的是同一批契约行为(状态机、提交类型、接口约定),不是同一个版本号——各语言各自发版,不用互相等。
  3. Rust 栈是第一个:引擎 4 个 crate 刚上 crates.io,集成栈刚并入八栈,属于"首发可用"状态。用的人少,问题反馈价值最高。

三、为什么六语言是卖点,而不是"炫技"

如果你只用一门语言,"六语言"听着确实像自嗨。它的实际价值是三句人话:

1. 流程数据不绑语言(无锁定)

jeeflow 引擎的持久化契约只有 5 张表wf_process_define / wf_process_instance / wf_process_task / wf_process_task_actor / wf_process_cc_instance,加上同一套状态机(实例 10/20/45、任务 10/20/99)和同一套提交行为(submitType 0~6 + 20)。六语言引擎读写的是同构数据——今天 Java 起的流程实例,Go 栈的引擎能直接读,因为表结构、状态码、字段约定都一样。

这对企业意味着:流程定义和历史数据是业务资产,不是某门语言的私有格式。技术栈要动的时候,工作流数据不用迁移。

2. 一套流程定义,六语言通用

15 个共享流程模板(审批/会签/条件分支/并行/驳回/抄送/一票否决……)只有一份,放在 jeeflow-java/jeeflow-core/src/test/resources/flows/,六语言 demo 直接读同一目录(Rust demo 就是 ../../jeeflow-java/.../flows 相对路径读进去的,PHP demo 同理)。流程 JSON 是 LogicFlow 格式,设计器画出来、哪个语言的后端都能跑。

3. 同一个库,换个语言接着用

一键部署的八栈共享同一个 MySQL 种子镜像(mldong-plus 库,45 张表:wf_process_* 8 + sys_* 23 + biz_* 11 + dev_* 3),同一个演示账号。想对比"同一个流程 Java 和 Go 跑起来有没有差别",起两个栈、连两个库,答案就是没有差别——这正是验收在验证的事。

一句话:六语言不是让你同时用六门语言,而是保证你不会因为选了某门语言,就被它锁死


四、一条 curl 背后:deploy.sh 做了什么

deploy.sh 不长,逻辑对八栈一致(以 Rust 栈为例):

1# 1. 拉镜像(API 默认固定生产 tag)
2docker compose -p "$PROJECT_NAME" pull
3# 2. 启动四容器:backend + frontend(nginx) + mysql + redis
4docker compose -p "$PROJECT_NAME" up -d
5# 3.  MySQL healthy
6# 4. 轮询真实登录,直到返回 "code":0
7for i in $(seq 1 60); do
8    body=$(curl -s -m 3 -X POST "http://127.0.0.1:28100/sys/login" \
9      -H "Content-Type: application/json" \
10      -d '{"userName":"superAdmin","password":"123456"}' || true)
11    if echo "$body" | grep -q '"code":0'; then
12        echo "✅ API 就绪"; break
13    fi
14    sleep 3
15done
16

两个值得知道的工程约定:

  • 就绪判定是"登录成功",不是"端口通了"。端口可连但应用没起来(冷启动、数据源没连上)会被继续等,直到真实登录返回 code:0 才算部署完成。
  • 八栈共享同一个前端镜像,nginx 里硬编码了 proxy_pass http://backend:8080/——所以所有栈的后端容器内必须监听 8080。Go 栈就栽在这:GoFrame 默认端口 18084,第一次接入时前端 /api/ 全 502,登录页卡死;改成 8080 才通。这种"藏在别人配置里的契约"是多栈共用的最大暗坑,现在写在 compose 注释里了。

八栈端口各段错开,一台服务器同时起 8 套不冲突:

前端API
boot42108024000
boot32218025100
boot22208025000
goframe2008023000
nestjs2708027000
fastapi2318026100
laravel1808218083
salvo2808028100

(每栈还有各自的 MySQL/Redis 端口,compose 里有;清理用 docker compose -p <项目名> down -v。)


五、为什么说"发布过的字节 = 你拿到的字节"

deploy.sh 拉的后端镜像 tag 是 compose 里参数化的:${BACKEND_IMAGE:-生产tag}

  • 你(用户)拉的是固定生产 tag——这个 tag 对应的镜像,是先在"候选 tag"上把四层验收(L0 部署就绪 / L1 API 形状契约 / L2 API 语义冒烟 / L3 前端全流程 E2E)全部跑绿之后,才原样晋升(retag,不重建,镜像 ID 不变)的;
  • 最近一轮(2026-08-24 七栈 + 08-25 Rust 栈):八栈 L0–L2 全部 19/19,L3 全部 14 过 / 1 固定 skip / 0 失败,单栈 6~8 分钟。

发布链路上周还堵过一个更隐蔽的坑:Rust 引擎 v1.0.0~1.0.4 五个 tag 的发布 CI 全部显示 success,但 crates.io 上四个 crate 全是 404——账号邮箱没验证,上传被拒,而脚本失败后没 exit 1,照样打印"✅ published"。假成功比失败危险:失败会拦你,假成功会让"已发布"变成既定事实。修了两条:任一 crate 失败即标红退出;留一条 gh workflow run release.yml -f tag=<tag> 的重触发路径。

发布链路的铁律:"报告成功"必须等于"可验证地成功"——镜像要回拉验 ID,包要仓库实查。


结语

一条命令,几分钟后有一套能点的工作流应用;六语言任选,数据不绑死任何一门。

这就是本篇的全部。引擎内部怎么设计(状态机、流程定义、DDD、SPI、会签)前 8 篇已经拆过,这一季讲"引擎长什么样"之后的事——它怎么以可部署、可验证、可替换的形态交到用户手里。

下一篇进入联邦的方法论:第 10 篇 · 跨语言对齐方法论:参考实现先行 + 契约测试 —— 同一份契约在六语言里怎么对齐、怎么验证、升级为什么必须严格串行?


参考资料


下一篇预告第 10 篇 · 跨语言对齐方法论:参考实现先行 + 契约测试 —— 同一份契约在六语言里怎么对齐、怎么验证、升级怎么传播?


一条命令,十分钟:jeeflow 工作流应用的六语言一键部署》 是转载文章,点击查看原文


相关推荐


Fiber 与 PHP 8.6 Polling API 异步初探
BingoGo2026/8/13

Fiber 与 PHP 8.6 Polling API 异步初探 几周前的一篇文章曾介绍 Polling API RFC,并将其定位为被低估的提案,原因主要在于:报道往往漏掉了真正的动机——那是内部 php_poll.h API,而非用户态的 Io\Poll 类。这一判断至今仍然成立。不过随后收到了不少类似"好吧,可它到底能用来做什么?"的反馈。这是个合理的问题,也正是本文要回答的问题。 时机也恰到好处。该 RFC 以 33 票赞成、1 票反对、4 票弃权通过,并于 6 月 3 日投票截止,实


鸿蒙掌上驾考宝典应用开发15:答题交互组件——Exam 与 SelectComponent 全解析
麦田ya2026/8/3

第15篇:答题交互组件——Exam 与 SelectComponent 全解析 一、引言 答题交互是驾考应用最核心的用户交互场景。DriverLicenseExam 项目的 Exam 组件和 SelectComponent 组件共同实现了完整的答题交互体验,包括试题展示、选项选择、答案判断、答题卡、倒计时等。本文将深入解析这两个组件的实现。 二、Exam 组件架构 2.1 组件职责 Exam 组件是考试页面的核心容器,负责: 管理试题列表(Swiper 滑动切换)展示倒计时(模拟考试)管理答题


[V2X]音频数据流图
墨染天玑2026/7/26

Playback / Recording / Voice 三种场景的音频数据流框图: #mermaid-svg-nAP2CEPsCFL66meU{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}


Day 008:Agent 记得越多越好吗?短期与长期记忆的底层逻辑
kisbad2026/7/18

系列: 100 天系统学习 AI Agent 开发 当前阶段: Agent 基础与环境搭建 今日目标: 搞懂短期记忆与长期记忆的核心差异,建立记忆治理机制。 AI Agent 大模型 Agent开发 LangGraph 很多刚接触 Agent 开发的同学,在加上数据库之后都会有一种错觉:“我的 Agent 终于拥有长期记忆了,它可以记住一切!” 但实操下来往往会遇到这种尴尬场景:学习助手如果每次都问“你学到第几天了”,会显得很智障;可如果它把你随口抱怨的一句“我最近不想学 Python”永久保


离线优先:无网络权限的鸿蒙 Flutter 应用设计
程序员小Pyy2026/7/10

在万物互联的时代,做一个"断网"应用反而是最激进、也最负责任的设计选择。本文以 E-Brufen 为例,从架构哲学、存储设计、代码实现到用户体验,全面探讨离线优先应用的构建方法。 一、为什么选择离线? 1.1 一句话:零权限 打开 E-Brufen 的 ohos/entry/src/main/module.json5,你会看到这样一行配置: "requestPermissions": [] 一个空数组。没有 ohos.permission.INTERNET、没有 ohos.p


定时任务(root)与 Web(www)权限冲突问题——使用 ACL 彻底解决
半桶水专家2026/7/2

在 Linux 服务器中,权限冲突问是一个非常常见的问题。 例如: Cron 定时任务:root 用户执行 PHP(Nginx + PHP-FPM):www-data 或 www 用户执行 Apache:apache 用户执行 Tomcat:tomcat 用户执行 两个不同用户需要共同读写同一目录。 很多人第一反应就是: chmod -R 777 data/ 虽然能解决问题,但非常不安全。 Linux 提供了更好的方案——ACL(Access Contr


MySQL 8.0 实现 JSON 字段全文检索 | ngram 分词支持单字/字母/中英文混合搜索
勿忘初心12212026/6/23

MySQL 8.0 实现 JSON 字段全文检索 | ngram 分词支持单字/字母/中英文混合搜索 前言一、业务场景二、技术痛点三、概念解释3.1 ngram 中日韩分词器3.2 生成列(Generated Column)3.3 全文索引(FULLTEXT INDEX)3.4 停用词表3.5 BOOLEAN MODE(布尔检索模式) 四、环境五、MySQL 全局配置(my.cnf / my.ini)5.1 完整配置文件5.2 重启 MySQL 服务5.3 验证配置是否生效 六、创


Claude Codde 入门教程—— 从零到独立完成项目
fa_lsyk2026/6/15

Claude Code 入门教程 适合人群:技术小白、编程初学者、对 AI 编程感兴趣的所有人 学习目标:读完本文后,你能够独立使用 Claude Code 完成一个完整的 OCP 项目 阅读时间:约 45-60 分钟 难度等级:★☆☆☆☆(零基础友好) 目录 前言:你即将拥有的"超能力"什么是 Claude Code?—— 你的 AI 编程伙伴安装 Claude Code —— 3 步搞定第一次对话 —— 跟 AI 说"你好"核心概念:理解 Claude Code 的"


HDFS 频繁进入安全模式的原因及解决方案
数据小羊2026/6/8

你是否遇到过 HDFS 集群时不时进入安全模式(Safe Mode)的问题?这不仅会影响数据的读写,还可能导致整个 Hadoop 生态系统的应用出现异常。本文将深入分析 HDFS 安全模式的触发机制,以及如何有效解决这个棘手问题。 什么是 HDFS 安全模式? HDFS 安全模式是一种保护机制,在这种状态下,文件系统只允许读操作,不允许任何修改文件系统的操作。通常在 NameNode 启动时会进入安全模式,以确保文件系统的元数据和数据块信息的一致性。 为什么 HDFS 会频繁进入安全模


【Redis】网络高并发模型
步十人2026/6/1

目录 一、 核心场景:百万并发下的秒杀大考1. 传统多线程服务器会怎么样?2. Redis 凭什么能抗住?第一步:建立连接(非阻塞 + epoll)第二步:读取请求(非阻塞 I/O)第三步:执行命令(单线程串行,纯内存操作)第四步:返回结果(非阻塞写) 二、 深度对比:多线程阻塞 vs 单线程非阻塞三、 演进:Redis 6.0+ 的多线程 I/O 革命四、 微观视角:一个秒杀请求的时间线拆解五、 致命死穴:如果某个命令很慢怎么办?本篇总结 一、 核心场景:百万并发

首页编辑器站点地图

本站内容在 CC BY-SA 4.0 协议下发布

Copyright © 2026 聚合阅读