一、Cromwell性能瓶颈排查概述

1.1 先聊聊 Cromwell 的架构

做性能优化之前,你得知道 Cromwell 是怎么跑起来的。说白了,它就是一个工作流引擎,专门跑生物信息学、基因组学那种计算密集的 pipeline。

我个人习惯把 Cromwell 的架构拆成三层来看:

  • API 层:接收你的 WDL 请求,返回状态。它用 Akka HTTP 做异步通信。
  • 引擎层:核心调度逻辑。解析 WDL、拆分任务、管理依赖、决定哪个任务先跑。
  • 后端层:实际干活的地方。把任务提交给本地、HPC、或者云平台(比如 Google Cloud Batch、AWS Batch)。

我遇到过不少同学,上来就盯着后端看,觉得慢就是集群慢。其实很多时候瓶颈在引擎层——任务调度太激进,或者数据库 I/O 堵死了。

关键认知:Cromwell 不是单线程执行的。它内部有很多异步队列、数据库连接池、以及后端插件。任何一个环节卡住,整个 pipeline 都会变慢。

1.2 常见的瓶颈类型

根据我的现场排查经验,性能瓶颈基本逃不出下面这几类。你想想看,是不是很眼熟?

瓶颈类型典型表现常见原因
CPU 瓶颈Cromwell 进程 CPU 跑满,但后端任务没跑满WDL 拆得太细,引擎过度调度
内存瓶颈GC 频繁,或者 OOM 崩溃数据库连接池开太大,或者工作流元数据爆炸
I/O 瓶颈数据库写入慢,日志轮转卡MySQL 没调优,或者后端文件系统磁盘吞吐不够
并发瓶颈大量任务排队,后端资源空着Cromwell 的最大并发数配小了,或者后端插件限流
第三方依赖瓶颈调用外部 API 超时,文件传输慢网络延迟,或者对象存储(如 S3、GCS)的请求限制

嗯,这里要注意一个坑:很多所谓的“Cromwell 慢”,其实是你的后端集群本身就慢。我一开始也踩过这个坑——花了两天调 Cromwell 的线程池,最后发现是 HPC 的共享文件系统 NFS 挂了。

1.3 排查流程:一个四步法

我整理了一套自己的排查流程,几乎每次都能用。别嫌简单,照着做就行。

  1. 第一步:定界——先确认问题是 Cromwell 自身慢,还是后端执行慢。简单粗暴:看 Cromwell 日志里 job-polling 的间隔,如果 polling 正常但任务不结束,那就是后端问题。
  2. 第二步:量化——用量化指标代替感觉。看 CPU、内存、数据库连接数、任务排队长度。我个人习惯拿 top 和 mysqladmin status 先扫一遍。
  3. 第三步:定位——用 Cromwell 提供的 API 拿内部指标。比如 /api/engine/v1/version 看版本,/api/engine/v1/stats 看调度状态。再配合 jstack 看线程栈。
  4. 第四步:优化——根据上一步的结果,调整对应配置。调完重启,重新测。一次只改一个变量。

一个小技巧:我把这个四步法画成了一张流程图,每次排查前都贴屏幕上。你可以直接拿去用。

Cromwell 性能瓶颈排查流程(四步法) 1. 定界 Cromwell vs 后端? 2. 量化 CPU / 内存 / 数据库 / 排队 3. 定位 API / jstack / 日志 4. 优化 调配置 → 重启 → 验证 常用工具 top, jstack, mysqladmin Cromwell /stats API WDL 任务日志 🪤 常见误区 不要一上来就调线程池 先确认后端是否真的慢 数据库连接池别设太大 ✅ 定位并解决瓶颈

1.4 你需要准备的工具和环境

工欲善其事,必先利其器。我列个检查清单,你对照着准备好。

  • Cromwell 版本:建议 ≥ 85,旧版本有内存泄漏。可以用这个命令看:
curl -s 'http://localhost:8000/api/engine/v1/version' | python3 -m json.tool
  • 数据库:MySQL 8.0+,或者 MariaDB。别用 SQLite 跑生产,你会哭的。
  • 后端:本地模式也行,但正式排障建议用真实集群(HPC / 云 Batch)。
  • 监控:至少能看 CPU、内存、磁盘 I/O、网络。我个人习惯先装 htop 和 iotop。

⚠️ 避坑指南:我曾经在生产环境看到有人把 MySQL 连接池开到 200,Cromwell 直接挂了。数据库连接数不是越大越好,建议根据并发工作流数来算,一般 20~50 就够了。

1.5 一次真实的定界案例

讲个例子吧。有一次线上 Cromwell 执行一个 500 个任务的 WDL,跑了 6 个小时还没完。用户说“Cromwell 太慢了”。

我先看了眼 Cromwell 日志,发现 job-polling 每 10 秒一次,很规律。但后端任务的 wall time 很短,说明任务本身不慢。

问题出在哪?我查了 Cromwell 的 /api/engine/v1/stats,发现队列里积压了 300 多个“等待数据库写入”的任务。

降低数据库的 max_connections,同时调大了 Cromwell 的 workflow-option { write_to_cache: false }(临时关掉缓存写入),速度立刻上来了。嗯,这就是典型的 I/O 瓶颈。

核心思路:先通过日志和 API 把问题范围缩小,再针对性地调整配置。不要一上来就改几十个参数。

好了,这是第一讲。后面我们会深入每个环节的具体排查手段和优化策略。