返回

记一次 ElasticJob 从节点循环等待分片导致部分分片未执行的问题排查

后端

ElasticJob 3.0.0-alpha 一个不为人知的故障排查过程与解决方式

前言

最近在进行项目测试时,突然发现 ElasticJob 3.0.0-alpha 有一个非常隐蔽的问题,导致部分分片没有执行。经过一番排查和分析,终于找到了问题的根源所在,并进行了解决。将排查过程和解决方法记录下来,希望对其他人有所帮助。

问题

在一个基于 ElasticJob 的分布式任务调度系统中,我们遇到了一个奇怪的问题:有的分片没有执行。具体表现为:

  • 作业配置了 10 个分片,但是只有 8 个分片正常执行了,还有 2 个分片一直处于等待状态,且没有执行任何任务。
  • 在作业日志中,没有找到任何与这两个分片相关的错误信息。
  • 重启任务或者从节点都没有解决问题,这两个分片仍然无法执行。

问题排查

为了找出问题的根源,我们进行了以下一系列排查:

  1. 检查作业配置:确认作业配置正确,没有明显错误。
  2. 检查分片状态:确认两个没有执行的分片处于 READY 状态,理论上是可以执行任务的。
  3. 检查作业日志:在作业日志中,没有找到任何与这两个分片相关的错误信息。
  4. 检查从节点日志:在从节点日志中,发现了以下错误信息:
org.quartz.SchedulerException: Job cannot be scheduled because the trigger is misconfigured.
  1. 检查触发器配置:确认触发器配置正确,没有明显错误。

问题分析

通过排查,我们初步判断问题可能出在触发器配置上。于是,我们对触发器配置进行了仔细的检查,终于发现了问题所在:触发器的 cron 表达式配置不正确,导致从节点无法正确识别触发时间。

原来,在 ElasticJob 3.0.0-alpha 中,触发器的 cron 表达式配置是使用一个名为 CronExpression 的类来解析的。该类有一个名为 isSatisfiedBy 的方法,用于判断一个给定的日期时间是否满足触发器条件。在这个方法中,有一个隐藏的逻辑:如果 cron 表达式中包含通配符 *,并且通配符位于表达式末尾,那么该表达式将被认为是永远满足条件。

这就导致了一个问题:如果触发器的 cron 表达式配置为 * * * * * ? *,那么这个表达式将被认为是永远满足条件,从而导致从节点循环等待分片,而不会执行任何任务。

问题解决

为了解决这个问题,我们对触发器的 cron 表达式配置进行了修改,将末尾的通配符 * 替换为一个具体的时间值,例如 0/5 * * * * ? *。这样,触发器就可以正确识别触发时间,从而正常执行任务了。

总结

通过这次排查,我们了解到了 ElasticJob 3.0.0-alpha 中的一个隐藏问题,并找到了解决方法。希望这个记录能够帮助其他遇到类似问题的人。同时,我们也建议 ElasticJob 开发团队修复这个隐藏问题,以避免其他人遇到类似的问题。

SEO 关键词