3. 本地单机部署
先聊个题外话。我最早接触Cromwell时,项目组直接扔给我一个JAR包,告诉我“跑起来就行”。结果MySQL没配好,任务日志全丢了,排查了一整天。后来我养成了一个习惯——不管是用源码编译还是下载二进制包,都先把底层存储和数据库捋清楚。
这一节,咱们就一起从零搭一套本地单机Cromwell。说白了就是:Cromwell进程 + MySQL + 本地文件系统。你可以在自己的笔记本、服务器或者云主机上复现,完全够你开发调试和跑小规模工作流。
从源码还是二进制?我的选择
先说结论:快速验证用二进制,定制功能用源码。我个人的经验是,生产环境我倾向用官方构建好的二进制包(稳定),而我在做二次开发或调试时,会从源码编译。
下表对比了两种方式的典型差异:
| 对比项 | 二进制包(JAR) | 源码编译 |
|---|---|---|
| 获取方式 | 下载一个 JAR 文件 | clone 仓库,用 sbt 或 mvn 编译 |
| 版本可控性 | 只能选官方发布版 | 可以锁定任意 commit,甚至修改源码 |
| 构建时间 | 几十秒下载 | 首次编译十多分钟 |
| 依赖管理 | 无需安装sbt/Java SDK | 需要Java 11+、sbt/Maven |
| 我遇到的坑 | 官方包有时缺第三方驱动 | 编译时内存不够,交换分区慢得要命 |
这一节我们两种方法都演示一遍,你选喜欢的就行。
准备环境
开始前,确认你的机器上有:
- Java 11+(Cromwell 官方推荐 Java 11,我常用 OpenJDK 11)
- MySQL 8.0(5.7 也行,但 8.0 更稳)
- sbt(如果你要从源码编译)
- Git(克隆仓库用)
检查命令很简单:
java -version
mysql --version
git --version
sbt --version # 如果打算编译
方式一:从源码编译
克隆 Cromwell 仓库,我建议锁定一个稳定 tag,比如 85:
git clone https://github.com/broadinstitute/cromwell.git
cd cromwell
git checkout 85 # 或者你想要的版本
编译命令:
sbt assembly
这个过程它会下载依赖、编译、打包。我第一次编译等了快 20 分钟……嗯,你可以去泡杯茶。编译成功后会生成一个胖 JAR:cromwell-85-????????.jar。
export SBT_OPTS="-Xmx2g -Xms1g",否则 OOM 了别怪我没提醒。
方式二:下载二进制 JAR
更省事的方法。去 GitHub Releases 页面 找到最新版,直接下载 cromwell-XX.jar。命令行:
wget https://github.com/broadinstitute/cromwell/releases/download/85/cromwell-85.jar
搞定。我大多数时候用这种方式,除非需要修 bug。
配置 MySQL 数据库
Cromwell 默认用 H2 内存数据库,重启数据就没了。生产环境必须上 MySQL。先创建数据库和用户:
mysql -u root -p
CREATE DATABASE cromwell CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'cromwell'@'localhost' IDENTIFIED BY 'YourPassword';
GRANT ALL PRIVILEGES ON cromwell.* TO 'cromwell'@'localhost';
FLUSH PRIVILEGES;
然后写一个 Cromwell 配置文件,比如 cromwell.conf:
database {
profile = "slick.jdbc.MySQLProfile$"
db {
driver = "com.mysql.cj.jdbc.Driver"
url = "jdbc:mysql://localhost:3306/cromwell?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=UTC"
user = "cromwell"
password = "YourPassword"
connectionTimeout = 5000
numConnections = 5
}
}
这里注意时区参数 serverTimezone=UTC。我之前没加这个,Cromwell 启动时报错说数据库时区异常,加上了就好了。
配置本地文件系统
Cromwell 需要一个工作根目录,存放中间文件和输出。我习惯创建一个专用文件夹:
mkdir -p /data/cromwell/work
export CROMWELL_ROOT=/data/cromwell
在配置文件中加上文件系统后端:
backend {
default = "Local"
providers {
Local {
actor-factory = "cromwell.backend.impl.sfs.config.ConfigBackendLifecycleActorFactory"
config {
root = "/data/cromwell/work"
filesystems {
local {
localization = [
"hard-link",
"soft-link",
"copy"
]
}
}
}
}
}
}
我建议把 root 设在一个有足够磁盘空间的位置,否则跑几个任务就满了。
启动 Cromwell
最终启动命令很简单:
java -jar cromwell-85.jar server --config cromwell.conf
看到类似下面日志就成功了:
INFO o.eclipse.jetty.server.Server - Started @xxxxms
INFO c.r.c.CromwellServer - Cromwell Server started on port 8000
打开浏览器访问 http://localhost:8000,能看到 Swagger UI。你也可以用 curl 测试:
curl http://localhost:8000/api/workflows/v1/query
返回空的 JSON 数组说明正常工作。
mysql-connector-java-8.x.x.jar 放到 classpath 里。后来我干脆把驱动 jar 放到了 lib/ 目录下,启动时加 -cp "cromwell.jar:lib/*"。
整体架构图
下面这张图能帮你理解本地单机部署各组件的协作关系:
避坑指南
- MySQL 连接超时:我踩过坑,默认连接池太少,若同时提交多个工作流会报错。建议把
numConnections改成 10 以上。 - 文件系统权限:Cromwell 进程用户要对工作根目录有读写执行权限。我之前用
root启动,后来切普通用户忘了 chown,任务全失败。 - Java 版本问题:Java 8 能跑但官方不再支持,一旦遇到奇怪异常,直接换 Java 11。
- 时区导致的时间错乱:MySQL 和 Java 时区不一致,数据库里的时间字段对不上。统一用 UTC 最省心。
echo "hello")来验证部署。如果这能跑通,基本环境就没问题了。我从不用复杂工作流来测配置,浪费时间。
小结
本地单机部署的核心就是三件事:Cromwell 进程(源码或 JAR) + MySQL 元数据库 + 本地文件系统。你把这三者配好,一个开发调试环境就完成了。
我个人建议二进制包起步,等需要改源码时再编译。配置文件的重点就两个:数据库连接和文件系统目录。搞定这两个,Cromwell 就能跑起来。
另外记得,MySQL 驱动需要手动放进去。我把它列到环境变量里,这样后续升级时不用重复拷贝。