
Openjob 基于 Akka 架构的新一代分布式任务调度框架。支持多种定时任务、延时任务、工作流设计,采用无中心化架构,底层使用一致性分片算法,支持无限水平扩容。
如果您正在寻找一款高性能的分布式任务调度框架,支持定时任务、延时任务、轻量级计算、工作流编排,并且支持多种编程语言,那么 Openjob 肯定是不二之选(https://github.com/open-job/openjob)。
openjob 发布至今已更新到 1.0.7 新增支持 H2/TiDB 数据库,新增秒级任务、固定频率任务、广播任务、分片任务、Map Reduce 轻量计算。
秒级任务,支持 1~60 秒间隔的秒级延迟调度,即每次任务执行完成后,间隔秒级时间再次触发调度,适用于对实时性要求比较高的业务。

由于 Crontab 必须被 60 整除,如果需要每隔 50 分钟执行一次调度,则 Cron 无法支持。

MapReduce 模型是轻量级分布式跑批任务。通过 MapProcessor 或 MapReduceProcessor 接口实现。相对于传统的大数据跑批(例如 Hadoop 、Spark 等),MapReduce 无需将数据导入大数据平台,且无额外存储及计算成本,即可实现秒级别海量数据处理,具有成本低、速度快、编程简单等特性。
/** * @author stelin [email protected] * @since 1.0.7 */ @Component("mapReduceTestProcessor") public class MapReduceTestProcessor implements MapReduceProcessor { private static final Logger logger = LoggerFactory.getLogger("openjob"); private static final String TWO_NAME = "TASK_TWO"; private static final String THREE_NAME = "TASK_THREE"; @Override public ProcessResult process(JobContext context) { if (context.isRoot()) { List<MapChildTaskTest> tasks = new ArrayList<>(); for (int i = 1; i < 5; i++) { tasks.add(new MapChildTaskTest(i)); } logger.info("Map Reduce root task mapList={}", tasks); return this.map(tasks, TWO_NAME); } if (context.isTask(TWO_NAME)) { MapChildTaskTest task = (MapChildTaskTest) context.getTask(); List<MapChildTaskTest> tasks = new ArrayList<>(); for (int i = 1; i < task.getId()*2; i++) { tasks.add(new MapChildTaskTest(i)); } logger.info("Map Reduce task two mapList={}", tasks); return this.map(tasks, THREE_NAME); } if (context.isTask(THREE_NAME)) { MapChildTaskTest task = (MapChildTaskTest) context.getTask(); logger.info("Map Reduce task three mapTask={}", task); return new ProcessResult(true, String.valueOf(task.getId() * 2)); } return ProcessResult.success(); } @Override public ProcessResult reduce(JobContext jobContext) { List<String> resultList = jobContext.getTaskResultList().stream().map(TaskResult::getResult) .collect(Collectors.toList()); logger.info("Map Reduce resultList={}", resultList); return ProcessResult.success(); } @Data @AllArgsConstructor @NoArgsConstructor public static class MapChildTaskTest { private Integer id; } } 
分片模型主要包含静态分片和动态分片:
任务特性****
/** * @author stelin [email protected] * @since 1.0.7 */ @Component public class ShardingAnnotationProcessor { private static final Logger logger = LoggerFactory.getLogger("openjob"); @Openjob("annotationShardingProcessor") public ProcessResult shardingProcessor(JobContext jobContext) { logger.info("Sharding annotation processor execute success! shardingId={} shardingNum={} shardingParams={}", jobContext.getShardingId(), jobContext.getShardingNum(), jobContext.getShardingParam()); logger.info("jobCOntext={}", jobContext); return ProcessResult.success(); } } 
广播任务类型的任务实例会广播到应用对应的所有 Worker 上执行,当所有 Worker 都执行完成,该任务才算完成,任意一台 Worker 执行失败,任务就算失败。
广播任务类型可以选择多种,例如脚本或者 Java 任务。如果选择 Java ,还支持 preProcess 和 postProcess 高级特性。
/** * @author stelin [email protected] * @since 1.0.7 */ @Component("broadcastPostProcessor") public class BroadcastProcessor implements JavaProcessor { private static final Logger logger = LoggerFactory.getLogger("openjob"); @Override public void preProcess(JobContext context) { logger.info("Broadcast pre process!"); } @Override public ProcessResult process(JobContext context) throws Exception { logger.info("Broadcast process!") return new ProcessResult(true, "{\"data\":\"result data\"}"); } @Override public ProcessResult postProcess(JobContext context) { logger.info("Broadcast post process taskList={}", context.getTaskResultList()); System.out.println(context.getTaskResultList()); return ProcessResult.success(); } } 
1 eastcukt 2023-09-12 11:18:41 +08:00 via Android 有意思。已 star |