Skip to content

PowerJob:分布式任务调度、计算与工作流

凌晨两点的数据同步、每分钟的状态巡检、订单超时处理、全体节点上的日志清理,通常会从几段散落在业务系统里的定时代码开始。任务变多后,团队还会遇到另一组问题:谁在执行、失败后重试了几次、某台机器离线会怎样、日志到哪里看、多个任务怎样按依赖顺序衔接。

PowerJob 给出的答案是一套公司级调度中间件。团队统一部署 powerjob-server,各业务应用接入 powerjob-worker;任务的时间、并发、路由、重试和报警留在调度中心管理,真正的业务逻辑仍运行在业务应用中。PowerJob 还允许一次任务拆成子任务分发给多个 Worker,或者把多项任务编排成有向无环图(DAG)工作流。

这种边界决定了 PowerJob 的价值和成本。PowerJob 比单个应用内的 @Scheduled 或 Quartz 多出统一控制台、跨节点调度、在线实例治理与分布式计算,也要求团队维护 Server、关系型数据库、网络端口和账号权限。需要统一治理多条业务线任务的 Java 团队最容易获得收益;只有少量本地定时方法时,接入一套中心化平台往往偏重。

GitHub 仓库信息

信息内容
项目标题PowerJob
项目描述分布式任务调度与计算框架(仓库 README 的项目定位)
GitHub 仓库PowerJob/PowerJob
官网地址未公开
内容摘要统一管理定时任务、跨节点执行、Map/MapReduce 计算和 DAG 工作流,并覆盖 Spring Boot 接入、OpenAPI、生产运维与升级。

核心角色

PowerJob 的整体结构可以先压缩成 Server、Worker 和可选 Client 三类角色。

powerjob-server 提供 Web 控制台、计算触发时间、创建任务实例、选择 Worker、分发执行请求并收集结果。Worker 随业务应用启动,向 Server 发现和报告自身状态,接到请求后加载处理器并执行。powerjob-client 则把创建任务、立即运行、查询实例、停止任务和操作工作流等管理能力暴露给业务代码。

Worker 不是一台独立的“执行服务器”。常规 Java 业务任务直接随宿主应用部署,因此处理器能使用 Spring Bean、数据库访问层和业务服务;调度中心只负责何时、在哪个节点、以何种策略执行。仓库中的 Worker 自动配置确认了 Server 地址、应用名、通信协议、本地存储和任务容量等装配过程。

核心能力

时间与执行方式

固定提交中的时间策略枚举覆盖 API、CRON、固定频率、固定延迟、工作流触发和每日时间区间;执行方式枚举覆盖单机、广播、Map 和 MapReduce。两组选择解决的问题不同:前者决定何时产生实例,后者决定一次实例怎样使用 Worker 集群。

执行方式一次运行会发生什么典型场景主要代价
单机Server 从可用 Worker 中选择一个节点执行报表生成、数据同步、普通业务任务业务仍需保证重复执行时的幂等性
广播集群内所有符合条件的 Worker 都执行,并支持集群前置、后置处理清理本地缓存、刷新所有节点配置节点数会直接放大执行量
Map根任务生成子任务,PowerJob 把子任务分发到集群批量更新、文件或数据分片处理分片粒度过细会增加调度和网络开销
MapReduceMap 分发后集中读取子任务结果并执行 Reduce需要汇总统计的分布式计算Reduce 全量持有结果,子任务巨大时增加内存压力

Map/MapReduce 进一步改变了一次任务利用 Worker 集群的方式:PowerJob 不只是在多台机器中挑一台执行 Cron。处理器可以在运行时调用 map 生成业务自定义子任务,Worker 集群共同处理后再汇总。官方 MapReduce 示例同时提醒,分片大小需要在失败重试成本与 PowerJob 调度开销之间取舍。

任务与实例管理

任务定义保存名称、触发方式、处理器、并发、超时、重试、机器门槛、日志和报警等配置。每次触发会产生独立实例,控制台可以观察状态和日志,也可以立即运行、停止、取消或重试。处理器使用 TaskContext 读取静态任务参数 jobParams、OpenAPI 运行参数 instanceParams、当前重试次数、子任务、工作流上下文和调度元信息。

OmsLogger 能把处理器日志送到控制台。官方处理器文档和示例都提醒,在线日志会增加 Server 通信与存储压力:开发阶段适合使用 Server 日志,稳定任务更适合切换到本地日志并提高日志级别。日志可见性是一种可配置的运维能力,不应变成无上限的远程日志管道。

工作流与 OpenAPI

工作流用 DAG 描述任务依赖,例如 A 成功后并行执行 B、C,最后执行 D。上游处理器可以通过 WorkflowContext 追加键值数据,下游节点再读取;Worker 配置会限制单次追加数据长度。工作流适合批处理流水线,不替代需要补偿事务、人工审批或长时间状态编排的完整流程引擎。

powerjob-client 提供另一条入口。固定提交的客户端接口覆盖任务、任务实例、工作流和工作流实例操作;5.1.2 还允许用业务主键 outerKey 关联一次运行。业务系统因此可以创建 API 类型任务,再根据订单、批次或事件决定立即执行还是延迟执行。

Docker Compose 试用

这条路径的目标不是看到三个容器处于运行状态,而是亲手创建并完成一次任务,再从控制台找到实例、结果和日志。仓库根目录的 Compose 文件会启动 MySQL、PowerJob Server 和示例 Worker,适合本地试用,不是生产模板。

前置条件与安全边界

  • 已安装 Docker Engine 或 Docker Desktop,以及 Compose V2;
  • 本机的 77001008610010100773307808127777 端口未被占用;
  • 只在可信测试网络运行,避免把数据库和通信端口暴露到公网;
  • Compose 文件使用 latest 镜像和公开示例凭据。生产环境应固定经过验证的镜像版本,使用独立强密码和密钥管理,并限制网络入口。

在一个准备保存测试数据的目录中克隆仓库,然后切换到本文核对的版本:

bash
git clone https://github.com/PowerJob/PowerJob.git
cd PowerJob
git checkout v5.1.2
docker compose up -d
docker compose ps

这些命令来自仓库 Compose 结构与官方快速开始,本次研究没有实际启动容器。首次启动需要初始化 MySQL 和 Server,示例 Worker 可能先失败再重启。观察日志时使用服务名,不要只看单个容器是否存在:

bash
docker compose logs -f powerjob-server powerjob-worker-samples

当 Server 日志不再持续报数据库连接错误、示例 Worker 完成注册,并且浏览器能打开 http://127.0.0.1:7700/,基础环境才算可用。5.x 默认 PowerJob 账号为 ADMIN,仓库配置的本地初始密码为 powerjob_admin;登录后立即修改密码。进入“应用管理”,确认 powerjob-worker-samples 存在并能看到在线 Worker。

创建并运行一个任务

进入示例应用,打开“任务管理”并新建任务。下面这组值刻意选择 API 触发,避免等待定时器:

字段测试值作用
任务名称powerjob-first-run便于在实例列表检索
任务参数CN示例处理器会返回中文成功消息
定时信息API只由手工或 OpenAPI 触发
执行类型单机执行从一个可用 Worker 执行
处理器类型内置 Java使用示例 Worker 内已有类
处理器信息tech.powerjob.samples.processors.SimpleProcessor固定提交中的示例处理器全限定名
实例重试次数0避免第一次试用出现重试放大
Task 重试次数0让一次点击对应一次实际执行

保存后点击运行按钮,再进入“任务实例”。成功信号应同时包括:实例状态为成功;结果中出现示例处理器返回的“任务成功啦”;在线日志能看到当前任务参数或上下文。这个闭环验证了 Server 调度、Worker 注册、处理器加载、执行结果和日志回传,而不是只验证 Web 页面能打开。

常见失败可以按信号定位:

  • no worker available:先确认 Worker 与任务属于同一个 App,再检查 server-address、协议和对应通信端口;
  • fetch Processor failed:核对处理器类型、全限定类名或 Spring Bean 名称,确认类确实进入 Worker 的运行时 classpath;
  • 页面正常但任务一直等待:检查 Worker 在线状态、指定机器或 Tag、CPU/内存/磁盘门槛和最大实例数;
  • 日志为空:核对任务的 LogType 与 LogLevel,若使用本地日志则到 Worker 日志文件查看。

试用结束后可停止容器:

bash
docker compose down

Compose 使用宿主机 ./powerjob-data/ 保存数据。普通 down 不会主动删除该目录;需要清理测试数据时,应先确认目录内容和备份要求,再单独处理。

接入 Spring Boot Worker

本节使用 PowerJob 5.1.2。业务项目的 Spring Boot、JDK 和依赖树仍要在接入前做兼容性验证;仓库示例使用 Spring Boot 2.7.18,项目 POM 的编译目标是 Java 8,5.1.2 Release 声明已通过 JDK 21 编译与运行测试。

添加依赖与配置

xml
<dependency>
  <groupId>tech.powerjob</groupId>
  <artifactId>powerjob-worker-spring-boot-starter</artifactId>
  <version>5.1.2</version>
</dependency>

先在 PowerJob 控制台创建 App,例如 billing-service,再在业务应用中加入配置:

yaml
powerjob:
  worker:
    enabled: true
    app-name: billing-service
    server-address: 10.0.10.21:7700,10.0.10.22:7700
    protocol: http
    port: 27777
    store-strategy: memory
    max-result-length: 8192
    max-appended-wf-context-length: 8192

server-address 使用 Server 的 Web 端口,不加 http:// 前缀;多个地址用英文逗号分隔。Worker 的 port 必须能被 Server 回连,同一主机部署多个 Worker 时需要使用不同端口,也可以在 5.1.2 中配置非正数以选择随机端口。普通单机或广播任务偏向 memory;可能产生大量子任务的 Map/MapReduce 更适合 disk,以降低内存压力。

开发环境没有 Server 时,可以临时设 allow-lazy-connect-server: true 让宿主应用启动。这个选项只放宽启动时连接要求,不代表 Worker 已经注册,也不能作为集成测试通过的证据。

编写一个 Spring Bean 处理器

java
package com.example.billing.job;

import org.springframework.stereotype.Component;
import tech.powerjob.worker.core.processor.ProcessResult;
import tech.powerjob.worker.core.processor.TaskContext;
import tech.powerjob.worker.core.processor.sdk.BasicProcessor;

@Component("dailyBillingReport")
public class DailyBillingReportProcessor implements BasicProcessor {

    @Override
    public ProcessResult process(TaskContext context) {
        String reportDate = context.getJobParams();
        context.getOmsLogger().info("Generating billing report for {}", reportDate);

        // 调用业务 Service,并自行保证重复执行时的幂等性。
        return new ProcessResult(true, "report generated: " + reportDate);
    }
}

启动业务应用后,在 App 的 Worker 列表确认节点在线。新建任务时,处理器类型选择内置 Java,处理器信息填写 Bean 名称 dailyBillingReport;也可以填写处理器全限定类名。非 MapReduce 任务还支持在 Spring Bean 方法上使用 @PowerJobHandler,处理器信息写成 Bean名称#方法名全限定类名#方法名,固定提交的方法处理器示例展示了签名要求。

ProcessResult.success 决定 Task 成败,msg 有长度限制并可能被截断。异常可以抛出,但业务处理器通常应捕获可预期异常、记录必要上下文并返回明确结果。PowerJob 的失败重试不会自动让数据库写入、HTTP 调用或消息发送具备幂等性;业务代码需要使用唯一键、状态机、去重表或业务幂等键处理重复执行。

常见配置问题

高频任务的时间策略

官方快速开始的维护者回复指出,CRON 的最小调度间隔是 15 秒;需要秒级高频执行时选择固定频率或固定延迟。固定频率按触发节奏推进,固定延迟会参考前一次完成后的间隔,选择前需要明确任务是否允许重叠。

重试策略

实例重试会重跑整个实例,Task 重试只重跑失败 Task。单机任务若两项都设为 1,最坏可能执行 4 次。通常先把实例重试设为 0,再根据 Task 的幂等性与失败成本设置 Task 重试;大型 Map/MapReduce 的实例级重试尤其昂贵。

Worker 筛选

指定地址、Worker Tag、最大执行机器数,以及最低 CPU、内存和磁盘条件会共同缩小候选集。调试 no worker available 时,应先清空非必要筛选,再逐项恢复。Tag 适合环境或单元隔离,但不能代替网络隔离和权限控制。

Reduce 与在线日志

MapReduce 的 Reduce 阶段需要读取全部子任务结果;超大任务只需要分发计算而不需要集中汇总时,Map 更稳妥。在线日志同样会把 Worker 侧输出集中送到 Server,生产任务应限制数量、单条长度和级别,并为日志存储选择独立于核心调度数据的介质。

业务系统触发

需要按订单或批次触发任务时,先在控制台创建一个 API 类型任务,并为 App 设置独立密码。业务项目加入客户端:

xml
<dependency>
  <groupId>tech.powerjob</groupId>
  <artifactId>powerjob-client</artifactId>
  <version>5.1.2</version>
</dependency>
java
import java.util.Arrays;
import tech.powerjob.client.IPowerJobClient;
import tech.powerjob.client.PowerJobClient;
import tech.powerjob.common.response.ResultDTO;

IPowerJobClient client = new PowerJobClient(
    Arrays.asList("10.0.10.21:7700", "10.0.10.22:7700"),
    "billing-service",
    System.getenv("POWERJOB_APP_PASSWORD")
);

ResultDTO<Long> result = client.runJob(42L, "batch=2026-08-31", 0L);
if (!result.isSuccess()) {
    throw new IllegalStateException(result.getMessage());
}
Long instanceId = result.getData();

示例中的地址、App、密码和 Job ID 都是占位值。密码应来自密钥管理系统,不写进源码、镜像或普通配置仓库。PowerJobClient 初始化时会校验 App,并能在 Server 集群节点间请求;应用关闭时应释放客户端资源。

5.1.2 的 Server 默认配置 oms.auth.openapi.enable=false 是为旧客户端兼容保留的开关。固定提交的拦截器显示,关闭时 OpenAPI 请求直接放行。生产部署应先把所有调用方升级到支持令牌鉴权的客户端,再设置 oms.auth.openapi.enable=true,同时在网关或防火墙限制 OpenAPI 来源。

生产部署要点

Server 与数据层

生产环境至少需要一套受管控的关系型数据库。官方部署文档称核心持久层基于 Spring Data JPA,可适配多种关系型数据库;仓库提供的完整 Schema 和升级 SQL 以 MySQL 8 为基准,其他数据库或版本应在测试库让目标 Server 自动建表,再对比 Schema 并验证方言、索引和分页行为。

多台 Server 连接同一套核心数据库即可组成集群。Server 间主通信协议由 oms.transporter.main.protocol 决定,对应端口必须互通。默认端口关系如下:

端口默认职责暴露建议
7700Web 控制台、Worker 发现和 OpenAPI只对管理入口、Worker 与调用方开放,公网入口放在鉴权代理后
10086AKKA 通信只在启用 AKKA 的 Server/Worker 网络开放
10010HTTP 传输协议默认 Server 间主协议需要,按集群拓扑开放
10077MU 协议5.1.2 Release 标为 Beta,只建议开发环境验证

关系型数据库保存核心元数据。MongoDB、阿里云 OSS 或 MySQL 系列存储扩展用于在线日志和容器文件等非核心数据。若选择数据库存日志,官方部署文档建议使用独立库,避免日志流量影响调度主链路。

账号、权限和密钥

PowerJob 5.x 采用基于角色的访问控制。权限可以收口到 App、Namespace 或全局范围,角色包含观察、测试、开发和管理员等层级。初次部署会创建 ADMIN 超级管理员;生产配置应提供一次性强初始密码,首次登录立即修改,并把日常操作授权到最小范围的用户或企业账号体系。

不要沿用仓库 Compose 的数据库密码、App 密码或管理员密码。数据库凭据、邮件密钥、钉钉密钥、OSS 凭据和 App 密码应进入专用密钥系统。仓库的 SECURITY.md提供私下披露安全问题的渠道。

发布、监控与备份

生产变更至少建立以下检查:

  • 固定 Server、Worker 和 Client 版本,不使用 latest;先在预发验证版本兼容和数据库变更;
  • 监控 Server 可用性、数据库连接池、调度延迟、等待分发实例、Worker 在线数、任务失败率与报警通道;
  • 为核心数据库和日志存储分别制定备份、恢复与保留策略,并实际演练恢复;
  • Worker 滚动发布时观察注册与下线,长任务需要明确停止、超时、重试和重复执行策略;
  • 对任务创建、修改、立即运行、停止和 OpenAPI 调用保留最小必要权限与审计链路。

升级与迁移

仓库当前 Release 为 v5.1.2,并在 others/sql/schema/ 保存版本化 MySQL Schema,在 others/sql/upgrade/ 保存部分升级脚本。5.1.0 到 5.1.2 的脚本会为实例表增加 extend_valuemetaouter_key 和索引。官方也明确说明,脚本并不覆盖所有数据库与所有版本组合。

兼容升级可以按“备份与恢复演练、测试库 Schema 对比、预发 Server、Worker/Client 回归、灰度 Server、观察、全量”的顺序进行。跨不兼容大版本时,官方建议新旧 Server 与数据库环境并存,逐个 App 迁移 Worker,验证后再关闭旧调度环境。直接让新版本 Server 指向唯一生产库,会把数据库迁移和应用兼容风险压到同一时刻。

版本升级前至少核对三处信息:Release notes、目标版本的 Schema 与升级目录以及官方升级手册。数据库备份存在不等于能够恢复,切换方案需要包含回滚触发条件和旧环境保留时间。

适用场景与替代方案

需求重心更值得考虑的方向关键判断
多个 Java 应用需要统一任务治理、跨节点执行、Map/MapReduce 或 DAGPowerJob接受维护调度中心、数据库、网络和权限体系
单个应用只有少量定时方法Spring @Scheduled 或 Quartz组件更轻,但跨应用治理与可视运维需要自行补齐
团队主要需要中心化定时任务与简单执行器XXL-JOB 等同类调度平台对比执行模型、权限、日志、迁移与社区版本,而不只比较功能数量
任务天然是独立容器,并运行在 KubernetesKubernetes CronJob 或工作流系统与集群调度、镜像和资源模型更一致,业务内 Spring Bean 调用不再直接
流程包含人工节点、补偿事务和长周期业务状态专用工作流或流程引擎PowerJob DAG 偏任务依赖编排,不承担完整业务流程语义

采用 PowerJob 前最有效的下一步,是挑一个可回滚、可重复、能观察结果的真实批处理任务,在预发环境完成四项验证:一台 Worker 离线时怎样恢复,处理器重复执行是否幂等,日志和结果增长是否可控,Server/数据库故障后怎样恢复。四项结果比功能表更能说明 PowerJob 是否适合当前团队。

版本与验证边界

本文基于 PowerJob v5.1.2、固定提交 332179d,核对日期为 2026 年 8 月 31 日。仓库采用 Apache-2.0 许可证,GitHub 语言统计以 Java 为主;最新公开 Release v5.1.2 发布于 2025 年 8 月 17 日。

研究过程读取了中英文 README、官方产品手册、Release、Compose、Maven 模块、Server/Worker 配置、处理器 SDK 与示例、客户端接口、权限初始化、OpenAPI 鉴权、数据库 Schema 和升级脚本。没有构建或执行 PowerJob 源码,没有启动容器、连接数据库、登录在线试用环境或验证生产性能。文中的命令、默认值与机制属于固定来源和静态核对,不是运行时测试结论。

主要入口包括仓库主页官方产品手册快速开始Server 部署Worker 初始化处理器开发OpenAPI。官方手册与固定源码出现差异时,本文优先采用 5.1.2 固定提交,并把动态文档作为操作说明来源。

文章结论绑定 source commit;动态信息以核对日期为准。