Hatchet 版本演进深度解析:从动态并发控制到嵌入式引擎的全功能全景
2026/9/16 19:00:28 网站建设 项目流程

Hatchet 版本演进深度解析:从动态并发控制到嵌入式引擎的全功能全景

【免费下载链接】hatchet🪓 An orchestration engine for background tasks, AI agents, and durable workflows项目地址: https://gitcode.com/GitHub_Trending/ha/hatchet

本篇技术指南以 Hatchet 官方 CHANGELOG.md 为主体脉络,结合仓库源码(并发调度、配置加载、SDK、CLI 等实现)为你系统梳理 v0.70 至 v0.106 版本的核心功能演进:动态并发限制、共享并发、两类新的队列深度并发策略、幂等性与批处理任务、工作流暂停、嵌入式引擎、无认证开发模式与可观测性增强。读完本文,你将掌握 Hatchet 近期版本新增能力的语义、配置参数、底层实现原理与升级注意事项,并能在自己的任务编排实践中直接应用这些新特性。

版本节奏与演进主线

Hatchet 采用语义化版本号,迭代节奏紧凑:从 2025 年 8 月的 v0.70 系列到 2026 年 9 月的 v0.106.5,一年内跨越 40 多个版本。整体演进主线可以归纳为四条:

  1. 并发与调度能力深化:从基础并发策略演进到动态并发限制(per-key CEL 表达式)、跨工作流共享并发、内存索引并发调度;
  2. 任务控制面扩展:引入幂等性 Key、批处理任务、工作流暂停、slot cost 高级分配;
  3. 开发者体验升级:嵌入式引擎(Embedded Mode)、无认证开发镜像、CLI quickstart 用例模板、四个官方 SDK(Go / Python / TypeScript / Ruby)同步迭代;
  4. 可观测性与运维硬化:丰富的 Prometheus 指标、独立的数据保留期配置、TLS 版本控制、会话表自动清理、大量调度器与队列死锁/竞态修复。

下表是主要里程碑的速览(完整细节见后文各节):

版本日期核心主题
v0.106.52026-09-08动态并发限制、共享并发、两个新并发策略、租户隔离安全修复
v0.105.162026-08-31CANCEL_QUEUED_EXCEPT_NEWEST / OLDEST 策略落地、引擎修复
v0.105.22026-08-25工作流暂停、成员级 payload 可见性、TS/Python Embedded 早期 Beta
v0.101.272026-08-17幂等性 Key、批处理任务、只读 VIEWER 角色、队列深度指标
v0.98.92026-07-28slot cost、幂等性(四 SDK)、Go 嵌入式引擎、内存索引默认开启
v0.94.102026-07-14无认证开发镜像、quickstart --use-case、独立保留期、流监听器自动重连
v0.90.132026-06-29UserSession 自动清理、多单位时长解析修复、调度冷启动优化
v0.89.02026-06-09TLS 最低版本配置、cron 按需触发、性能优化
v0.83.0 ~ v0.85.x2026-03 ~ 05组织/租户管理、RBAC、SSO、追踪(Trace)支持、负载测试增强
v0.78.x ~ v0.82.x2026-01 ~ 03官方 Ruby SDK、durable execution 重构、OTel 可观测性大改
v0.70.x ~ v0.75.x2025-08 ~ 2026-01v1 API 全面铺开、webhook、依赖注入、组织 UI、Hatchet CLI

并发控制:从固定策略到动态表达式

并发控制是近期版本投入最多的领域,v0.106.5 直接被称为 "concurrency-focused release"。

并发策略家族与调度分发

在底层实现上,所有并发策略都收敛到统一的入口RunConcurrencyStrategy,它根据策略枚举分发到不同的执行函数。见 scheduler_concurrency.go:

switch strategy.Strategy { case sqlcv1.V1ConcurrencyStrategyGROUPROUNDROBIN: res, err = c.runGroupRoundRobin(ctx, tenantId, strategy) case sqlcv1.V1ConcurrencyStrategyCANCELINPROGRESS: res, err = c.runCancelInProgress(ctx, tenantId, strategy) case sqlcv1.V1ConcurrencyStrategyCANCELNEWEST: res, err = c.runCancelNewest(ctx, tenantId, strategy) case sqlcv1.V1ConcurrencyStrategyCANCELQUEUEDEXCEPTNEWEST: res, err = c.runCancelQueuedExceptNewest(ctx, tenantId, strategy) case sqlcv1.V1ConcurrencyStrategyCANCELQUEUEDEXCEPTOLDEST: res, err = c.runCancelQueuedExceptOldest(ctx, tenantId, strategy) }

策略枚举定义在 models.go:

V1ConcurrencyStrategyCANCELQUEUEDEXCEPTNEWEST V1ConcurrencyStrategy = "CANCEL_QUEUED_EXCEPT_NEWEST" V1ConcurrencyStrategyCANCELQUEUEDEXCEPTOLDEST V1ConcurrencyStrategy = "CANCEL_QUEUED_EXCEPT_OLDEST"

两类新的队列深度策略:CANCEL_QUEUED_EXCEPT_NEWEST / OLDEST

v0.105.16 与 v0.106.5 先后引入并完善了CANCEL_QUEUED_EXCEPT_NEWESTCANCEL_QUEUED_EXCEPT_OLDEST两个策略(对应 PR #4793、#4847 等)。它们的语义是:

  • CANCEL_QUEUED_EXCEPT_NEWEST:在同一个并发组内,取消所有已排队(QUEUED)的运行,仅保留最新排队的那个,直到在途运行完成——概念上类似"防抖(debouncing)";
  • CANCEL_QUEUED_EXCEPT_OLDEST:对称地,仅保留最旧排队的运行,取消其余排队项。

两者的典型价值:当高频触发大量排队任务时,只让最新的(或最旧的)请求真正执行,避免"排队长龙"浪费资源。从源码看,其实现位于 scheduler_concurrency.go 的runCancelQueuedExceptNewest/runCancelQueuedExceptOldest:两者都先通过TryAdvisoryLock(而非阻塞锁)获取策略级 advisory lock 以降低锁竞争,未获取到锁时直接返回空的RunConcurrencyResult(标记FailedAdvisoryLock: true),随后创建父级临时表、执行RunParentCancelQueuedExceptNewest/RunChildCancelQueuedExceptNewestSQL 查询挑出被取消的任务,再调用DeleteTasksFromQueue将它们从队列中移除。父子(parent/child)策略链路都走同一套"父级准入 + 子级出队"的流程。

动态并发限制:per-key CEL 表达式

v0.106.5 允许按并发 Key 动态设置并发上限:并发限制不再是一个固定数字,而是一个 CEL 表达式,针对每个 key 独立求值。官方示例:

input.tier == 'premium' ? 10 : 1

含义:premium等级的用户可以同时运行 10 个工作流,其他用户只能同时运行 1 个。这一能力在存储层由V1StepConcurrency结构体的MaxRunsExpression字段承载(见 scheduler_concurrency.go),与静态的MaxConcurrency并存——MaxRunsExpression负责动态上限,MaxConcurrency仍是静态上限的兜底。

共享并发:跨工作流的并发规则

在此之前,如果要限制workflow_aworkflow_b合计每个用户最多 10 个并发运行,通常需要引入一个父级 router 任务做中介。v0.106.5 引入共享并发(shared concurrency):直接创建一条并发规则,让多个任务与工作流同时消费它,从而替代 router 任务模式,减少一跳编排开销。

内存索引并发调度(默认开启)

v0.98.9 将SERVER_CONCURRENCY_IN_MEMORY_INDEX_ENABLED的默认值改为true:并发策略改为默认基于内存索引 + outbox方式评估,而非每个调度周期都查询 Postgres。配置项在 server.go 中定义并绑定环境变量:

// ConcurrencyInMemoryIndexEnabled controls whether the in-memory index + outbox approach is used for concurrency strategies ConcurrencyInMemoryIndexEnabled bool `mapstructure:"concurrencyInMemoryIndexEnabled" json:"concurrencyInMemoryIndexEnabled,omitempty" default:"true"`

同时 v0.83.2 引入了"内存中、带 Key 的锁队列"来保护RunConcurrencyStrategy,v0.79.4 修复了链式并发闸门中的跨策略 slot 污染问题——这些修复共同保证了并发调度在高负载下的正确性。

幂等性与批处理任务

v0.101.27 正式发布幂等性 Key(Idempotency Keys)批处理任务(Batch Tasks),v0.98.9 将幂等性 Key 扩展至全部四个 SDK(Go / Python / TypeScript / Ruby)。

  • 幂等性 Key:任务和工作流可以声明幂等性 Key,重复触发不会产生重复运行。Key 在 TTL 内或直到认领它的运行达到终态之前一直被持有。v0.101.27 同时优化了幂等性查找——当任务不携带任何 Key 时直接跳过查找,避免无谓查询。
  • 批处理任务:将多个任务聚合为一次批量提交,减少 API 调用次数与下游资源占用。

补充细节:v0.73.40 起对定时运行的幂等性 Key 错误做了静默处理,v0.73.0 修复了定时运行与幂等性 Key 检查之间的竞态——说明该功能从引入到稳定经历过多轮打磨。

工作流暂停与调度管理

v0.105.2 正式上线工作流暂停(Workflow Pause),适用于"工作流错误率高需要紧急止血"或"白天排队、夜间集中执行"等场景。暂停的语义:

  • 在途(in-flight)运行继续执行完毕;
  • 新触发的运行保持排队,直到取消暂停(排队受队列 TTL 限制);
  • cron 与定时触发可以选择"排队"或"丢弃"运行。

配套调度增强:v0.79.16 增加"按需更新定时 cron 触发"的队列;v0.89.0 允许通过 Dashboard 直接按需触发 cron 与定时运行,不必等待下一个调度 tick;v0.79.14 为 cron 增加了秒级粒度。引擎侧 v0.105.16 修复了暂停工作流时并发 slot 迁移到暂停队列表(paused queue items table)的问题,v0.79.23 则移除了已被废弃的旧暂停查询。

嵌入式引擎与本地开发体验

Go SDK Embedded:进程内引擎

v0.98.9 起,Go SDK 可以在进程内运行完整引擎(指向你自己的 Postgres),用于本地开发与端到端测试。API 见 embedded.go:

func WithEmbedded(opts ...EmbeddedOption) v0Client.ClientOpt func WithEmbeddedDatabaseURL(url string) EmbeddedOption

用法示例:

client, err := hatchet.NewClient(hatchet.WithEmbedded( hatchet.WithEmbeddedDatabaseURL("postgres://..."), ))

参考完整示例 embedded/main.go。v0.105.2 将 Embedded 扩展为 TypeScript 与 Python SDK 的早期 Beta:SDK 可以直接在你自己的 worker 旁边拉起一个完整引擎,非常适合本地开发、端到端测试与 CI。

无认证开发镜像

v0.94.10 引入一组开发镜像(hatchet-api-devhatchet-engine-devhatchet-admin-devhatchet-dashboard-dev),无需管理 API Token 即可运行,适合开发与测试环境。通过 CLI 启动:

hatchet server start --disable-auth

该命令以hatchet-lite-dev替代hatchet-lite。需要明确的是:这种模式在 Hatchet 二进制中内嵌了一个全局 worker API key,只能用于开发与测试环境

CLI 与 quickstart 用例模板

v0.75.0 引入 Hatchet CLI;v0.94.10 为hatchet quickstart增加--use-case标志,首个用例是scheduled——一个按 cron 调度、同时支持按需运行的工作流 Go 模板(实现见 quickstart.go,模板布局契约见 templater/selection.go)。v0.98.9 起,所有接受--profile的 CLI 命令在没有显式配置时使用默认或唯一 profile 而不再交互式询问;在无终端会话(如 CI)中,需要交互选择的命令会以明确的错误提示告终,hatchet server start在无默认配置时会将新 profile 设为默认。

v0.105.2 还让hatchet-liteSIGTERM传递给引擎,容器关闭时优雅退出而不再等待被强制杀死。

可观测性增强

Prometheus 指标

近期版本持续扩充租户级指标(tenant metrics):

  • v0.101.27:hatchet_tenant_queued_to_assignedhatchet_tenant_queued_to_assigned_time_seconds按工作流名拆分导出;hatchet_tenant_queue_size增加workflow_name标签;新增hatchet_tenant_additional_metadata_queue_sizegauge,按 additional metadata 键值对报告队列深度——只有以prom_前缀开头的 Key 才会被导出(显式 opt-in,控制基数);注意一个条目会计入它所携带的每一个 metadata Key,跨 Key 求和没有意义。
  • v0.94.10:新增 worker pool 的 slot 利用率指标hatchet_tenant_worker_label_slots(总槽位)、hatchet_tenant_used_worker_label_slots(在用)、hatchet_tenant_available_worker_label_slots(空闲),按标签分组。
  • v0.72.2:新增 worker slot Prometheus 指标。
  • v0.86.9:task stats 端点新增taskNames查询参数,便于 KEDA 场景使用;v0.73.92 为 task stats 增加最旧排队与运行中任务信息。

独立的数据保留期配置

v0.94.10 起,OLAP 与核心数据保留期可以独立配置(此前共用一个默认值):

环境变量作用
SERVER_LIMITS_OLAP_PARTITION_RETENTIONOLAP 分区保留期
SERVER_LIMITS_CORE_PARTITION_RETENTION核心分区保留期
SERVER_LIMITS_DEFAULT_TENANT_RETENTION_PERIOD未设置上述两项时的兜底默认值

对应绑定代码见 server.go。

追踪与日志

  • v0.82.0 完成可观测性大改与 traces 支持;v0.83.x 系列持续修复 OTel 相关死锁、span 命名与自引用问题;
  • v0.98.9 起,run trace 视图中的引擎行会携带 workflow / task / event 名称徽章,重试任务显示重试序号,使重复 span(如hatchet.engine.workflow_run)一眼可辨;
  • v0.79.35 池化 gzip writer 降低 RabbitMQ 消息压缩分配;v0.73.73 增加 gzip 压缩支持;
  • v0.73.66 增加 REST API 插桩;v0.77.32 引入 OTel Collector。

TLS 与安全基线

v0.89.0 为引擎与客户端引入最低 TLS 版本配置:

环境变量默认值
SERVER_TLS_MIN_VERSION1.3
HATCHET_CLIENT_TLS_MIN_VERSION1.3

绑定见 server.go。v0.106.5 还发布了安全公告:引擎侧的 satisfied durable event 查找现在按租户过滤,强制 durable event 日志的租户隔离(对应 GHSA-992g-9cr3-vm5x)。

稳定性、运维与升级注意

UserSession 自动清理

v0.90.13 修复了UserSession表无界增长问题:新增每小时清理任务,自动删除过期与孤儿会话。升级前可对 Postgres 执行可选的一次性批量清理(次数不限):

DELETE FROM "UserSession" WHERE ctid IN ( SELECT ctid FROM "UserSession" WHERE NOT ( ("userId" IS NOT NULL AND "expiresAt" >= NOW()) OR ("userId" IS NULL AND "createdAt" >= NOW() - INTERVAL '24 hours') ) LIMIT 10000 );

注意:10000的 LIMIT 可按需调整。

更严格的时长校验

v0.90.13 修复了多单位时长字符串(如42m30s)被静默截断的解析 bug,并收紧注册时的时长校验。升级前需检查工作流定义:以下形式将被拒绝——带符号值、裸数字、亚毫秒单位(ns/us)、以及混用d/w/y的形式。这些写法过去会被接受并静默转换,现在会在注册时直接报错。

调度器与队列的持续修复

CHANGELOG 中反复出现调度器与消息队列的稳定性修复,例如:

  • v0.105.2:被逐出(evicted)的任务现在可以超时而不是挂起;重试退避在高重试次数下不再溢出;缺失行查找返回NotFound而非Internal
  • v0.105.16:durable DAG 的 on-failure 任务不再被跳过;worker 心跳在拒绝非活跃监听流之前记录;
  • v0.106.5:分区在UpdateDurableEventLogEntriesSatisfied中被剪枝;CEL 求值不一致修复;任务分配时重复行不再触发 on-conflict 错误;
  • v0.101.27:每租户操作定时器在启动时跨完整间隔抖动、持久化间隔懒加载,避免多租户部署中控制器重启引发的查询风暴;worker label 亲和性相同的任务在并列 worker 间轮询分配,而不是挤满单台 worker。

其他值得关注的运维项

  • 仪表盘子路径:v0.101.27 起仪表盘可通过BASE_PATH(静态文件服务器)或LITE_FRONTEND_BASE_PATH(hatchet-lite)部署在子路径而非域名根路径;
  • 只读角色:v0.101.27 新增只读VIEWER租户成员角色;v0.105.2 允许按成员限制 payload 可见性——VIEWER成员可以查看运行、工作流、worker、事件、日志与指标,但看不到 payload 内容、也不能做任何修改;
  • 消息队列配置解耦:v0.98.9 起 best-effort pub/sub 与 durable queue 独立配置,pub/sub 可运行在 Postgres 上而 durable 消息保留在 RabbitMQ,现有部署无需新配置;
  • CLI 匿名遥测:v0.98.9 起 CLI 在调用时上报匿名使用数据(可用hatchet rate-limits管理限流,或从 TUI 交互式操作);
  • v1 化推进:v0.74.x 移除 v0 专有数据库查询与路径,v0.83.57 起所有 list partition 调用仅针对 v1 租户,v1_(runs|dags|tasks)_olap移除状态分区(v0.83.46)——升级到这些版本意味着全面切换到 v1 数据模型。

总结:如何跟上 Hatchet 的演进

Hatchet 的版本演进呈现清晰的路径:并发调度从"静态规则"走向"动态表达式 + 共享规则 + 内存索引"任务控制面从"单次触发"走向"幂等、批量、可暂停"开发体验从"完整自托管"走向"嵌入式引擎 + 无认证开发镜像 + CLI 模板"可观测性从"基础日志"走向"全量 trace + 细粒度租户指标"

对使用者而言,本文建议按以下顺序落地新能力:

  1. 升级前先阅读本文的"稳定性、运维与升级注意"一节,重点检查时长字符串与UserSession清理脚本;
  2. 对高频、易重放的触发,启用幂等性 Key;对大批量提交,改用批处理任务;
  3. 需要按用户等级或业务维度差异化限流时,使用动态并发限制(CEL 表达式);需要跨工作流限流时,使用共享并发;
  4. 对"高频触发只执行最新一次"的场景,优先尝试CANCEL_QUEUED_EXCEPT_NEWEST
  5. 本地开发与 CI 优先尝试 Embedded 模式或无认证开发镜像,降低环境搭建成本。

相关源码与配置的进一步探索入口:并发调度实现、并发策略枚举、服务端配置项、Go SDK 嵌入式 API、嵌入式示例、CLI quickstart。

【免费下载链接】hatchet🪓 An orchestration engine for background tasks, AI agents, and durable workflows项目地址: https://gitcode.com/GitHub_Trending/ha/hatchet

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询