openjob对比powerjob

768 阅读5分钟

前言

powerjob和openjob都是新时代的分布式无锁设计调度服务,两者的开源协议都是apache 2.0,这个很重要。我们现在用的是powerjob,稍微修改适配了业务。本次对比也是基于我们使用的经验得出的,仅供参考,如有不对,欢迎指正。 另外由于powerjob已经在项目中使用,所以我肯定是更熟悉powerjob一些。

powerjob和openjob简单对比

对比一 支持的任务类型

单机广播map reduce分片workflow
powerjob
openjob

虽然都写着支持,但是他们的实现还是有些区别的。先说powerjob,它的相对更加完善,配置项更完善,比如任务的生命周期配置,调度策略可选(健康优先/随机),fix-rate任务可以支持到毫秒级别,这是目前我们业务需要的。

1.png

2.png

作为对比openjob支持的任务细节没有powerjob那么完善,时间频率也有一些限制。另外openjob的ui上没有workflow相关的菜单。可能还没推出,但是我看代码里是有的,可能要等后期完善后开放此功能。另外在权限方面,openjob也尚未完善,但是它预留的设计我觉得是比powerjob优秀的,简而言之,它在权限方面的设计可以类比nacos的实现,namespace+app的配合应该能满足我们大部分的需求,powerjob在这点上也可以加把劲,目前甚至没有可以查看所有app的管理页面。

另外openjob的延迟任务是需要依赖redis实现的,如果需要开启该功能就必须配置redis,这里设计的比powerjob复杂,但是作为用户来说,如果调度任务能直接分为 fix_rate 和 fix_delay ,那么我会更好理解。

4.png image.png

对比二 spring兼容性

两个框架在对spring的兼容方面都提供了worker的starter版本,简单看了下,都采用了processor的接口方案,用户通过接口继承实现调度任务即可,或者使用提供的方法注解,由框架自动生成代理processor,这点实现上大差不差。

另外两者都没有提供调度任务自动注册的方法,powerjob提供了powerjob-client模块,通过该模块我们可以手动编写代码,通过提供的api注册调度任务。openjob我没有发现相关模块。

powerjob优秀点

  1. 毫秒级别的任务触发,内部使用了原子netty时间轮的设计,达到精准触发。
  2. 方便的sdk设计。
  3. 将heavyTask的控制交给worker节点处理,减轻了server的负担,使server能拉起更多的job。

openjob优秀点

  1. slot槽设计,我想它的设计可能来自哈希环或者redis-cluster的slot设计。所有的job新增的时候都会绑定一个slot,通过slot在集群中的漂移,来完成任务的负载均衡,这点的设计上看起来要比powerjob更好一些,但是也更复杂一些,powerjob的最小单位是app,一个完整的app运行在一台powerjob-server上,而openjob将这个范围缩小到了job。
  2. openjob的调度也使用了时间轮。
  3. 更多样的告警通知方式,钉钉/微信等。
  4. 预设了很多的日志存储方式mysql/es等,openjob的日志实现和powerjob稍有些差异,openjob是通过自定义的logAppender经过actor发送到server,也就是说它是按行发送的,powerjob是按次任务打包发送的,需要用到它的OmsLog,相对而言我更喜欢直接使用Logger门面的方式。

其它

在项目中使用powerjob的过程中,遇到的问题我也列一下,希望对大家有用。

  • 毫秒级任务在所有worker下线的情况下,会产生一大堆的任务实例日志,在数据库写入一堆记录的同时也会在服务器生成一堆空的日志文件,日志文件的数量甚至无法通过rm命令直接删除。

    我的处理办法是增加了一种中间状态NO_WORKER,即找不到worker的时候不再新建任务实例,需要修改代码,我提了ISSUE一直也没得到回应。

  • Worker挂掉的时候,新的实例因为HealthFirst的缘故在60S内一直尝试挂掉的Worker。

    woker实例的健康判断超时时间为60S,在选择Worker清单的时候,先分成两个part,把心跳时间10S内的放在第一梯队里,超过的放第二梯队,这样可以保证Worker挂掉的时候,不至于新的实例因为HealthFirst的缘故在60S内一直尝试挂掉的Worker。

  • fixedRate任务的精确程度很低,没有按预期的调度,powerjob默认对秒级任务的支持并不怎么完善,设计的时候没有考虑这种情况

    分析原因是,延迟任务的调度完成后,系统通过另起线程轮询状态导致不能及时响应,现在收到process上报成功/失败后直接更新状态并发起下一轮调度。修改代码,添加了onTaskExecuted方法,及时响应处理成功。

结论

powerjob和openjob都是目前很优秀的分布式调度框架的方案,大家可以按需取用,如果你需要精确到毫秒级的方案那么powerjob必选,如果不是那么我觉得目前两者都是成为你的选择。另外我也想知道为什么不管是powerjob还是openjob都没有使用cluster+sharding模块,而是直接使用remote模块外加自己实现集群控制。

欢迎大家一起讨论。