概述

您可以通过配置文件或Java命令行来配置Cromwell设置。

查看教程如何配置Cromwell获取更多信息。

配置示例

您可以在Cromwell示例配置中找到选项说明和示例配置段落,并在示例提供者文件夹中查看后端提供者示例。

自定义配置文件

您使用HOCON编写配置文件。

要使用您的配置文件运行,您应该从cromwell.examples.conf中复制相关配置段到一个新文件中,根据需要进行修改,然后通过以下方式将其传递给Cromwell:

$ java -Dconfig.file=/path/to/yourOverrides.conf cromwell.jar ...

要创建您自己的配置文件,首先新建一个文本文件,例如 my.conf

在文件开头,请将application.conf文件包含在自定义配置之前。

# include the application.conf at the top
include required(classpath("application"))

从这里开始,复制或添加其他配置值和/或带有自定义设置的节。

# include the application.conf at the top
include required(classpath("application"))

# Add customizations
webservice.port = 58000

您的配置文件可以指定类似JSON格式的配置节或点分隔值。以下两个示例是等效的。

类JSON格式段落:

include required(classpath("application"))
webservice {
  port = 8000
  interface = 0.0.0.0
}

点分隔的值:

include required(classpath("application"))
webservice.port = 8000
webservice.interface = 0.0.0.0

通过命令行配置

除了使用配置文件外,您还可以使用点分隔的配置名称直接在Java命令行上指定值:

$ java -Dwebservice.port=8080 cromwell.jar ...

高级配置

警告: 这些高级配置值可能会显著影响Cromwell的性能。

服务器

默认情况下,Cromwell服务器会绑定到0.0.0.08000端口。
然后您可以通过浏览器访问http://localhost:8000
要修改这些设置,只需在配置文件中编辑以下值:

webservice {
  port = 9000
  interface = 0.0.0.0
}

上述配置将使用端口 9000

Cromwell使用akka-http来处理请求。如需更高级的配置设置,请参阅akka-http文档。

例如,要将请求超时时间增加到30秒,您可以在配置文件中添加以下段落:

akka.http.server.request-timeout = 30s

输入/输出

I/O 节流

某些后端会施加I/O限制。例如Pipelines API对每秒可执行的查询数量设置了配额。

您可以在system.io配置中有效控制和限制分配给这些操作的请求数量和资源:

system.io {
  number-of-requests = 100000
  per = 100 seconds
}

I/O 弹性

I/O操作可能因多种原因失败,从网络故障到服务器错误。其中一些错误并非致命性的,可以重试。

Cromwell会在遇到此类可重试错误时重试I/O操作,在放弃并失败前会尝试有限次数。可以通过以下配置选项设置这个次数(更准确地说,是将会进行的尝试次数):

system.io {
  number-of-attempts = 5
}

工作流

最大并发工作流数

Cromwell对同时运行的工作流数量设有可配置的上限。您可以通过以下设置将默认限制从5000进行调整:

system.max-concurrent-workflows = 5000

新工作流轮询速率

Cromwell会定期查找要启动的新工作流,该间隔以秒数配置。您可以通过修改以下值来更改默认的20秒轮询频率:

system.new-workflow-poll-rate = 20

最大工作流启动次数

每次轮询时,只要有待启动的新工作流且未达到system.max-concurrent-workflows数值上限,Cromwell都会接收有限数量的新提交项。默认情况下最多启动1个工作流,您可以通过以下设置覆盖该默认值:

system.max-workflow-launch-count = 1

中止配置

Cromwell将使用与以下默认配置值等效的设置扫描中止请求。在大多数情况下,无需覆盖这些默认值。

system {
  abort {
    # How frequently Cromwell should scan for aborts.
    scan-frequency: 30 seconds

    # The cache of in-progress aborts. Cromwell will add entries to this cache once a WorkflowActor has been messaged to abort.
    # If on the next scan an 'Aborting' status is found for a workflow that has an entry in this cache, Cromwell will not ask
    # the associated WorkflowActor to abort again.
    cache {
      # Guava cache concurrency.
      concurrency: 1
      # How long entries in the cache should live from the time they are added to the cache.
      ttl: 20 minutes
      # Maximum number of entries in the cache.
      size: 100000
    }
  }
}

数据库

使用MySQL数据库

Cromwell跟踪工作流的执行情况,并将任务调用的输出存储在SQL数据库中。Cromwell支持外部MySQL数据库或临时内存数据库。

默认情况下,Cromwell使用内存数据库,该数据库仅在JVM运行期间存在。这提供了一种在本地快速运行工作流的方式,无需设置MySQL,但这也使得工作流执行具有一定临时性。

要将Cromwell配置为指向MySQL数据库,首先需要创建一个空数据库。在下面的示例中,数据库名称为cromwell

然后,按如下方式编辑配置文件中的 database 段落:

database {
  profile = "slick.jdbc.MySQLProfile$"
  db {
    driver = "com.mysql.cj.jdbc.Driver"
    url = "jdbc:mysql://host/cromwell?rewriteBatchedStatements=true"
    user = "user"
    password = "pass"
    connectionTimeout = 5000
  }
}

注意:Cromwell 支持 MySQL 8.0 和 8.4 版本。

Cromwell 计划支持所有当前维护的LTS版本。

要查看db配置段所有可能的参数和值,请参阅slick文档

基于MySQL数据库的Cromwell服务器

您可以使用docker-compose将Cromwell的Docker镜像(通过sbt docker本地构建或从Dockerhub获取)与MySQL的Docker镜像进行关联。

要更改使用的Cromwell版本,修改compose/cromwell/Dockerfile中的标签

本地

从该目录运行docker-compose up将启动一个运行在MySQL实例上的Cromwell服务器,并使用本地后端。

使用的默认配置文件可以compose/cromwell/app-config/application.conf找到。 要覆盖它,只需将包含自定义application.conf的卷挂载到/app-config目录(参考jes-cromwell/docker-compose.yml中的示例)。

谷歌云

jes-cromwell目录展示了如何通过配置文件和环境变量来自定义原始compose文件的示例。

它使用主机上的应用程序默认凭据。要使用它,请确保您的gcloud是最新的,并且您的application-default credentials已设置好。

然后运行 docker-compose -f docker-compose.yml -f jes-cromwell/docker-compose.yml up 以启动一个基于MySQL数据库、使用Google Cloud后端的Cromwell服务器。

MySQL

MySQL容器中的数据目录挂载到compose/mysql/data,这样数据在docker-compose down后仍能保留。

要禁用此功能,只需移除volume section of docker-compose.yml中的./compose/mysql/data:/var/lib/mysql这一行。

请注意,在这种情况下,数据仍会通过docker-compose stop命令保留,该命令会停止容器但不会删除它。

注意事项

要在后台运行Cromwell,请在命令末尾添加-ddocker-compose up -d

要查看特定服务的日志,请运行 docker-compose logs -f 。 例如 docker-compose logs -f cromwell

有关docker compose的更多信息:Docker compose doc

插入批次大小

Cromwell会将记录排队然后批量插入数据库以提高性能。您可以通过以下方式调整Cromwell批量插入的数据库行数:

database {
  insert-batch-size = 2000
}

独立的元数据库

此功能应被视为实验性,未来可能会发生变化。

Cromwell存储了每个作业和工作流的元数据。这些元数据面向终端用户,包含作业结果的路径、开始和结束时间等信息。元数据的增长速度远快于引擎内部其他数据。

要为元数据使用单独的数据库,请在database配置部分下,为metadata配置带有自定义设置的子路径。

database {
  # Store metadata in a file on disk that can grow much larger than RAM limits.
  metadata {
    profile = "slick.jdbc.HsqldbProfile$"
    db {
      driver = "org.hsqldb.jdbcDriver"
      url = "jdbc:hsqldb:file:metadata-db-file-path;shutdown=false;hsqldb.tx=mvcc"
      connectionTimeout = 3000
    }
  }
}

如果没有找到metadata的覆盖配置,Cromwell将回退使用根database配置下的设置。

数据库时区

Cromwell的默认配置假定其MySQL数据库设置为UTC时区。

以下MySQL配置通常默认为UTC时区,可直接与Cromwell配合使用: - Google CloudSQL - Docker中运行的官方MySQL镜像

这些配置可能会使用系统或本地时区替代: - 原生安装在工作站或服务器上的MySQL

如果Cromwell启动失败并显示类似以下消息

The server time zone value 'XXX' is unrecognized or represents more than one time zone.

你可以通过在数据库连接URL中添加选项&serverTimezone=UTC来解决这个问题:

url = "jdbc:mysql://host/cromwell?rewriteBatchedStatements=true&serverTimezone=UTC"

使用此选项不会改变数据库的底层时区;相反,它会使Cromwell在与数据库通信时"使用UTC时间",由数据库服务器为您执行时区转换。

在Postgresql中使用Cromwell

要使用Postgresql作为数据库,您需要安装并启用大对象扩展。如果该扩展已存在,只需执行以下命令即可完成数据库设置:

$ createdb cromwell
$ psql -d cromwell -c "create extension lo;"

Cromwell中的Postgresql配置与MySQL非常相似。示例:

database {
  profile = "slick.jdbc.PostgresProfile$"
  db {
    driver = "org.postgresql.Driver"
    url = "jdbc:postgresql://localhost:5432/cromwell"
    user = "user"
    password = "pass"
    port = 5432
    connectionTimeout = 5000
  }
}

如果您希望多个数据库用户能够从Postgresql数据库中读取Cromwell的数据,您需要创建一个所有相关用户都能访问的角色,并调整Cromwell以使用此角色。这是因为每个大型对象都由写入它的角色拥有,并且只能由该角色读取。

首先,在执行Cromwell时传递以下选项。这些选项将确保Cromwell的数据库表由角色拥有,而非初始登录用户。 * -DengineSharedCromwellDbRole=your_role 用于控制拥有引擎表的角色 * -DsharedCromwellDbRole=your_role 用于控制拥有元数据表的角色

接下来,使用配置键pgLargeObjectWriteRole设置应拥有所有大对象的角色,如下所示。 如果您未使用Postgresql,此配置将不会生效。配置的登录用户可以是任何被授予共享角色的用户。

database {
  profile = "slick.jdbc.PostgresProfile$"
  pgLargeObjectWriteRole = "your_role"
  db {
    driver = "org.postgresql.Driver"
    url = "jdbc:postgresql://localhost:5432/cromwell"
    user = "user"
    password = "pass"
    port = 5432
    connectionTimeout = 5000
  }
}

使用基于文件的数据库运行Cromwell(无需服务器)

目前不支持SQLite。不过,HSQLDB支持使用持久化文件运行。 可通过以下配置进行设置:

database {
  profile = "slick.jdbc.HsqldbProfile$"
  db {
    driver = "org.hsqldb.jdbcDriver"
    url = """
    jdbc:hsqldb:file:cromwell-executions/cromwell-db/cromwell-db;
    shutdown=false;
    hsqldb.default_table_type=cached;hsqldb.tx=mvcc;
    hsqldb.result_max_memory_rows=10000;
    hsqldb.large_data=true;
    hsqldb.applog=1;
    hsqldb.lob_compressed=true;
    hsqldb.script_format=3
    """
    connectionTimeout = 120000
    numThreads = 1
   }
}

Explanation of the options (see also http://hsqldb.org/doc/2.0/guide/dbproperties-chapt.html):

  • jdbc:hsqldb:file:cromwell-executions/cromwell-db/cromwell-db; 这将确保所有持久化文件最终都会存放在cromwell-executions内的cromwell-db文件夹中。
  • shutdown=false. 这确保数据库不会被关闭,除非Cromwell明确执行关闭操作。
  • hsqlldb.default_table_type=cached。默认情况下hsqldb使用内存表,这将确保数据写入磁盘并减少内存使用。
  • hsqldb.result_max_memory_rows=10000 . 限制临时表在内存中的行数。
  • hsqldb.tx=mvcc 这是使用hsqldb运行时的cromwell默认设置。
  • hsqldb.large_data=true. Cromwell会创建需要打开的大型数据库。
  • hsqldb.applog=1. 记录与数据库相关的错误。
  • hsqldb.lob_compressed=true. 压缩大对象数据。这可以节省一些空间。需要注意的是,大对象是单独压缩的。由于许多大对象数据会相似,整个数据库仍然会包含大量冗余。
  • hsqldb.script_format=3. 压缩脚本(内部使用gzip)。解压后仍可正常打开。
  • connectionTimeout = 120000 当运行cromwell时再次打开大型数据库文件需要一定时间。默认的超时设置3000毫秒(3秒)不够用,因此设置为120000毫秒(120秒)。
  • numThreads = 1. 这将限制Cromwell的CPU使用率,在高性能计算环境中非常有用。

与MySQL(或PostgreSQL)服务器对比: 优势:

  • 无需搭建服务器
  • 无需担心数据库用户、密码和权限问题。这些将由文件系统权限处理。

缺点:

  • Cromwell需要更多内存
  • 数据库文件将占用大量磁盘空间(数GB的情况并不罕见)
  • Cromwell与数据库的交互速度较慢。

与默认内存数据库的对比: 优势:

  • 所需内存大幅减少。
  • 启用调用缓存

缺点:

  • 较慢。

中止

Control-C (SIGINT) 中止处理器

对于支持中止作业的后端,可以配置Cromwell在收到Control-C(也称为SIGINT)时自动尝试中止所有调用。所有当前正在运行的调用也会将其状态设置为Aborted

要明确开启或关闭此功能,请设置配置选项:

system {
  abort-jobs-on-terminate=true
}

或者,通过命令行选项 -Dsystem.abort-jobs-on-terminate=true

默认情况下,运行java -jar cromwell.jar server时该值为false,而运行java -jar cromwell.jar run 时为true。

阅读中止部分了解更多关于中止操作的工作原理。

调用缓存

调用缓存功能使Cromwell能够检测过去是否运行过某个作业,从而避免重复计算结果。
了解更多请参阅Call Caching

要启用调用缓存,请将以下内容添加到您的Cromwell配置中:

call-caching {
  enabled = true
  invalidate-bad-cache-results = true
}

call-caching.enabled=true(默认值:false)时,Cromwell将能够引用或复制之前运行作业的结果(在适当情况下)。 当invalidate-bad-cache-results=true(默认值:true)时,Cromwell将使任何包含无法在缓存命中时访问的文件的缓存结果失效。这通常是期望的行为,但如果由于外部原因(例如用户认证差异)导致此失败,则可能不需要此行为。

Cromwell也接受工作流选项来覆盖缓存的读写行为。

文件哈希策略选项

在判断作业是否已运行时,Cromwell会获取作业输入文件的哈希值以比较文件内容。用户可以配置用于哈希文件的算法。该配置针对每个后端及其支持的文件系统单独设置,可用选项根据后端是本地还是基于云而有所不同。

配置应添加到后端的config部分:

backend {
  providers {
    GcpBatch {
      config {
        filesystems {
          gcs {
            caching {
              hashing-strategy = ["md5", "identity"]
            }              
          }
          drs {
            caching {
              hashing-strategy = "crc32c"
            }              
          }
        }
      }
    }
    Local {
      config {
        filesystems {
          local {
            caching {
              hashing-strategy = "md5"
            }              
          }
        }
      }
    }
  }
}
云存储的调用缓存策略选项

Cromwell支持配置一种或多种云文件哈希策略。如果提供了策略列表,Cromwell将按顺序尝试每种算法,直到找到可用的哈希值。该功能旨在支持不保证具有单一哈希类型的文件。Cromwell永远不会为了计算哈希值而下载文件,所有云哈希策略都依赖于文件元数据。

每个文件系统支持有限的哈希策略集。 * gcs Google存储支持: * crc32c 默认值,保证存在 * md5 对于通过分段上传创建的文件将不存在(Cromwell本身不使用分段上传) * identity 使用存储桶名称、blob名称和生成号来唯一标识存储对象。这比通常用于调用缓存的要求更严格 - 当使用identity时,Cromwell不会在仅输入文件内容相同的任务之间进行调用缓存,输入必须是完全相同的GS对象。这可能会破坏使用中间文件作为输入的任务的调用缓存。 * s3 AWS S3支持: * etag 默认值,保证存在 * drs 数据存储服务支持: * crc32c * md5 * etag * sha256 * 鉴于DRS数据集的多样性,无法保证所有文件都存在哈希值。DRS的默认哈希策略是["crc32c", "md5", "sha256", "etag"]

关于GCS哈希策略的说明

对于某些需要运行大量相同任务副本(仅输入文件不同)的高通量生产用例,crc32c的哈希冲突率可能高得难以接受。为了在减少可调用缓存任务集合的代价下显著降低碰撞概率,我们推荐使用hashing-strategy: ["md5", "identity"]。该策略会在MD5哈希存在时使用md5算法,否则回退到极其严格的identity策略(例如通过分段上传创建的文件)。由于Cromwell创建的所有GCS文件都保证具有md5值,identity策略仅对用户提供的工作流输入文件生效。

本地文件系统的调用缓存策略选项

Cromwell支持为本地文件哈希配置单一策略。如果未提供配置,将默认使用md5。有关与此设置交互的其他配置,请参阅下方的本地文件系统选项。

  • hash based options. These read the entire file. These strategies work with containers.
    • xxh64 (社区支持*)。该算法采用xxHash的64位实现版本,专为文件完整性哈希优化,相比md5可提供超过10倍的性能提升。
    • md5. 知名的md5sum算法
  • Path based options. These are based on filepath. Extremely lightweight, but only work with the soft-link file caching strategy and can therefore do not work with containers by default.
    • path 生成路径的MD5哈希值。
    • path+modtime 会基于路径及其修改时间生成一个md5哈希值。
  • Fingerprinting. This strategy works with containers.
    • fingerprint (社区支持)尝试通过获取文件的最后修改时间(自纪元起的毫秒数,十六进制表示)+ 大小(字节数,十六进制表示)+ 文件前10 MB的xxh64校验和来为每个文件创建指纹*。相比基于哈希的选项,这种方法更加轻量级,同时仍具有足够的唯一性,不太可能发生冲突。该策略适用于生成多GB大小文件的工作流,且在cromwell实例上对这些文件进行哈希处理会导致CPU或I/O问题的情况。 注意:此策略需要将硬链接作为复制策略,因为复制会更改最后修改时间。

(*) fingerprintxxh64 策略是由Cromwell的HPC社区支持的功能。核心Cromwell团队不提供官方支持。

(**) 此值可配置,详见下文。

本地文件系统选项

在配置(共享文件系统)后端上运行作业时,Cromwell在后端的配置部分提供了一些额外选项:

      config {
        filesystems {
          local {
            # When localizing a file, what type of file duplication should occur. 
            # possible values: "hard-link", "soft-link", "copy", "cached-copy".
            # For more information check: https://cromwell.readthedocs.io/en/stable/backends/HPC/#shared-filesystem
            localization: [
              "hard-link", "soft-link", "copy"
            ]

            caching {
              # When copying a cached result, what type of file duplication should occur. 
              # possible values: "hard-link", "soft-link", "copy", "cached-copy".
              # For more information check: https://cromwell.readthedocs.io/en/stable/backends/HPC/#shared-filesystem
              # Attempted in the order listed below:
              duplication-strategy: [
                "hard-link", "soft-link", "copy"
              ]

              # Possible values: md5, xxh64, fingerprint, path, path+modtime
              # For extended explanation check: https://cromwell.readthedocs.io/en/stable/Configuring/#call-caching
              # "md5" will compute an md5 hash of the file content.
              # "xxh64" will compute an xxh64 hash of the file content. Much faster than md5
              # "fingerprint" will take last modified time, size and hash the first 10 mb with xxh64 to create a file fingerprint.
              # This strategy will only be effective if the duplication-strategy (above) is set to "hard-link", as copying changes the last modified time.
              # "path" will compute an md5 hash of the file path. This strategy will only be effective if the duplication-strategy (above) is set to "soft-link",
              # in order to allow for the original file path to be hashed.
              # "path+modtime" will compute an md5 hash of the file path and the last modified time. The same conditions as for "path" apply here.
              # Default: "md5"
              hashing-strategy: "md5"

              # When the 'fingerprint' strategy is used set how much of the beginning of the file is read as fingerprint. 
              # If the file is smaller than this size the entire file will be read.
              # Default: 10485760 (10MB). 
              fingerprint-size: 10485760

              # When true, will check if a sibling file with the same name and the .md5 extension exists, and if it does, use the content of this file as a hash.
              # If false or the md5 does not exist, will proceed with the above-defined hashing strategy.
              # Default: false
              check-sibling-md5: false
            }
          }
        }
      }

工作流日志目录

要更改Cromwell写入工作流日志的目录,请通过以下设置修改目录位置:

workflow-options {
    workflow-log-dir = "cromwell-workflow-logs"
}

保留工作流日志

默认情况下,Cromwell会在工作流完成后删除每个工作流的日志以减少磁盘使用。您可以通过将以下值设置为false来更改此行为:

workflow-options {
    workflow-log-temporary = true
}

通过Sentry进行异常监控

Cromwell支持Sentry,这是一项可用于监控应用程序日志中异常报告的服务。

要在Cromwell中启用Sentry监控,请使用系统属性输入您的DSN URL:

sentry.dsn=DSN_URL

作业Shell配置

Cromwell 允许在系统范围或每个后端作业中配置自定义shell来运行用户命令,而非始终使用默认的 /bin/bash。要在系统范围内设置作业shell,请使用配置键 system.job-shell;若需针对特定后端设置,则使用 .job-shell。例如:

# system-wide setting, all backends get this
-Dsystem.job-shell=/bin/sh
# override for just the Local backend
-Dbackend.providers.Local.config.job-shell=/bin/sh

对于配置后端,作业shell的值将在${job_shell}变量中可用。请参阅Cromwell的reference.conf以了解如何将其用于Local后端的默认配置示例。

工作流心跳

Cromwell ID

每个Cromwell实例都会被分配一个cromwell_id。默认情况下,Cromwell ID的格式为cromid-<7位随机十六进制数>。 用户可以用自定义标识符替换字符串中的"cromid"部分。例如:

system {
  cromwell_id = "main"
}

这将生成一个cromwell_id,格式为main-<7_digit_random_hex>。每次Cromwell重启时,ID中的随机部分会改变,但main前缀保持不变。

如果不应生成Cromwell ID的随机部分,请设置配置值:

system {
  cromwell_id_random_suffix = false
}

心跳存活时间

当一个Cromwell实例开始运行或恢复工作流时,它会将上述cromwell_id与名为"心跳"的时间戳一起存储在工作流的数据库行中。随着工作流继续运行,Cromwell实例会间歇性地更新运行中工作流的心跳。如果Cromwell实例终止,在经过一定的存活时间(TTL)后,该工作流将被视为已放弃,并由另一个可用的Cromwell实例恢复执行。

通过配置值调整心跳TTL:

system.workflow-heartbeats {
  ttl = 10 minutes
}

默认TTL为10分钟。TTL选项允许设置的最短值为10秒。

心跳间隔

心跳写入的间隔可以通过以下方式调整:

system.workflow-heartbeats {
  heartbeat-interval = 2 minutes
}

默认间隔为2分钟。最短间隔选项为3.333秒。间隔时间不得超过TTL。

心跳失败关机

当Cromwell在一段时间内无法写入心跳时,它将自动关闭。这段时间可以通过以下方式调整:

system.workflow-heartbeats {
  write-failure-shutdown-duration = 5 minutes
}

默认关闭时长为5分钟。允许的最大关闭时长等于TTL。

心跳批处理大小

工作流心跳由Cromwell内部排队并以批次写入。当达到可配置的批次大小时,即使心跳间隔尚未结束,批次中的所有心跳也会同时写入。

此批量阈值可通过以下方式调整:

system.workflow-heartbeats {
  write-batch-size = 100
}

默认批处理大小为100。

心跳阈值

Cromwell一次写入一批工作流心跳。当待写入心跳的内部队列超过可配置的阈值时,instrumentation可能会发送一个指标信号,表明心跳负载高于正常水平。

此阈值可通过以下配置值进行设置:

system.workflow-heartbeats {
  write-threshold = 100
}

默认阈值为100,与心跳批处理大小的默认值相同。

YAML

最大节点数

当检测到Yaml输入中存在循环引用时,Cromwell会抛出错误。但用户仍可能构造小型无环YAML文档来消耗大量内存或CPU资源。为限制解析过程中的处理负荷,系统对每个YAML文档的解析节点数设置了上限。

此限制可通过配置值进行调整:

yaml {
  max-nodes = 1000000
}

默认限制为1,000,000个节点。

最大嵌套深度

YAML嵌套的最大深度存在限制。如果您决定增加此值,可能还需要通过使用-Xss-XX:ThreadStackSize来增加Java虚拟机的线程堆栈大小。

此限制可通过配置值进行调整:

yaml {
  max-depth = 100
}

默认限制为最大嵌套深度1,000。