Apache 2.0 · Java 与 Kotlin · Spring Boot 2/3/4 · PostgreSQL 15+

工作流持久化执行,以 Java 库的形式

JES 可靠地运行您的作业与工作流:它们能在崩溃、重启以及跨机器迁移中存活——状态完好无损。无需部署独立服务器。只要已有 Spring Boot 和 PostgreSQL,您就万事俱备。

一条依赖。三张表。零基础设施。

OrderWorkflow.java
@Service
public class OrderWorkflow {
    // 启动订单处理工作流
    public void start(String orderId) {
        JobOptions options =
            JobOptions.jobWithExternalId(orderId);
        jobSystem.startJob(options,
            this::processOrder, String.class, orderId);
    }

    // 崩溃与重试自动恢复
    public String processOrder(String orderId) {
        String receipt = jobSystem.execute(
            paymentService::chargePayment,
            String.class, orderId);
        try {
            jobSystem.execute(
                deliveryService::deliverGoods, orderId);
        } catch (JobFailure e) {
            jobSystem.execute(
                paymentService::rollbackPayment,
                orderId, receipt);
            throw e;
        }
        return receipt;
    }
}
30,000 / 秒作业处理速度(c8r16 数据库)
1–2 毫秒从提交作业到开始执行
3 张表PostgreSQL——全部状态
∞作业执行时长不受限制

工作流引擎该做的一切——都在您的应用之内

作业层级

父子作业可无限嵌套,支持顺序或并行执行。子作业天然幂等:相同方法 + 相同参数 → 只执行一次,结果会被缓存。

默认容错

至少一次执行保证、无限重试、故障后自动恢复——即使所有应用实例全部宕机也能恢复。

持久化状态与上下文

具名、类型化的状态槽在作业重启后依然存在,并可从外部读取。类型化上下文可在作业间传递——支持多态。

信号与取消

向运行中的作业发送任意消息、从外部取消、必要时中断。信号沿层级向下传递。

资源限制

可限制并发作业总数、按作业类型或按资源限制。应用实例之间的均匀分配开箱即用。

可观测性

Micrometer 指标、trace_id/span_id 沿层级传播、Actuator HealthIndicator、内置 HTTP API 与作业历史搜索。

无需数据库的测试

轻量级 TestJobSystem 在单元测试中运行真实作业——无需 PostgreSQL,自动跳过延迟,限制重跑次数。

零停机升级

在应用持续运行的同时演进作业的成熟策略:方法版本化、按首次运行时间分支、先排空再更新。

四步即可运行

添加依赖

JES 已发布到 Maven Central。需要 Spring Boot 2.7+、Java 17+、PostgreSQL 15+。

pom.xml
<dependency>
  <groupId>dev.jesproject</groupId>
  <artifactId>job-execution-system</artifactId>
  <version>2.0.0</version>
</dependency>

创建数据库结构

通过 Liquibase 建立三张表:将仓库中的 db/job_execution_system 复制到你的迁移目录,并引入 changelog。

changelog-master.xml
<databaseChangeLog
    xmlns="http://www.liquibase.org/xml/ns/dbchangelog">

  <!-- JES 的表结构随库一同提供:
       将 db/job_execution_system 复制到你的迁移目录 -->
  <include file="job_execution_system/init/v2.0.xml"
           relativeToChangelogFile="true"/>

</databaseChangeLog>

启用 JES

在应用主类上添加一个注解。

Application.java
@SpringBootApplication
@EnableJobExecutionSystem
public class ExampleApp {
    public static void main(String[] args) {
        SpringApplication.run(ExampleApp.class, args);
    }
}

启动第一个作业

Spring Bean 的任何公共方法都会成为持久化作业——失败后自动重试直至成功。

HelloService.java
@Service
public class HelloService {
    private final JobSystem jobSystem;

    public void runHelloJobs() {
        jobSystem.startJob(this::hello, "World");
    }

    public void hello(String name) {
        // 至少执行一次,故障后自动恢复
        log.info("Hello, {}!", name);
    }
}

工作原理

三张表就是整个引擎

作业只是 PostgreSQL 表中的一行:方法、参数、父作业、状态、调度计划。没有隐藏状态——对 jobs、job_signals 和 job_data 三张表执行 SELECT,一切尽收眼底。

实例从队列领取作业

应用实例轮询数据表,用带 FOR UPDATE SKIP LOCKED 的短事务领取下一个作业——因此数十个实例可以水平扩展而互不干扰,工作自动流向空闲实例。

实例宕机不等于作业失败

每个执行器通过心跳确认存活。实例宕机后,其他实例会接管它的作业并重新执行——至少一次,状态完好无损。整个集群宕机也同样如此。

工作流是自我恢复的作业树

工作流作业会派生子作业——业务流程的步骤,可顺序或并行执行。子作业天然确定性:相同方法 + 相同参数 → 结果已在数据库中。因此父作业在任何地方重启时,已完成的步骤不会重复执行——工作流从停止处继续。

实际使用效果

几个小片段——每一段都是无需编写任何基础设施代码即可获得的保证。

并行分发到多个作业

每个订单一个子作业——并行执行、独立重试,全部完成后汇总结果。

OrderProcessor.java
// 每个订单一个子作业:并行执行、独立重试
public List<Report> processAll(List<Order> orders) {
    List<Job> jobs = jobSystem.startJobs(
        JobDefinition.ofList(this::processOrder, orders));

    // 等待全部子作业并收集结果
    return Job.getAll(jobs, Report.class).toList();
}

public Report processOrder(Order order) {
    // 相同参数 → 只执行一次,重跑时结果来自缓存
    return warehouse.reserve(order);
}

针对你的负载灵活调优

JES 开箱即用,默认值即是合理配置——无需任何配置。但每一项参数都开放可调:线程池、重试延迟、心跳、自动清理以及内置管理 API。

application.yml
job-execution-system:
  max-runner-count: 100    # 每实例的作业线程数
  jobs:
    new-check-interval: 200ms # 新作业启动速度
    heartbeat-rate: 850ms     # 故障实例检测
    heartbeat-timeout: 5000ms # 故障转移阈值
    delay-on-error: 0ms       # 重试前的暂停
  signals:
    new-check-interval: 1000ms # 信号投递延迟
  cleanup:
    enabled: false           # 旧作业自动清理
    expiration-period: P1Y8M5D
    cron: "0 0 */20 * * *"   # 清理计划
  api:
    enabled: false           # HTTP 管理 API
  • 默认值开箱即用

    以上所有值都是可选的——省略整个配置块,JES 也会以相同的默认值运行。

  • 按实例伸缩

    线程数、预取与心跳按应用实例设置;实例之间自动均衡。

  • 友好对待数据库

    轮询频率与 Hikari 连接池大小均可调整——连接数受到严格限制。

所有配置项均为可选——示例中显示的即默认值。

为分布式系统的硬核场景而生

幂等执行 至少一次代码执行 定时与延迟作业 MapReduce 风格处理 分布式多线程 事务性发件箱(Outbox) 分布式重试 Saga 编排

你的 Postgres 已经是工作流引擎