使用 XXL-Job 碰到的几个问题
1. 测试环境:看不到新启动的执行器
这是一个比较少见的问题。经过排查发现,新机器的系统时间不正确,比正常时间晚了几个小时。
由于 XXL-Job 的心跳机制会定期检查执行器的注册信息,并更新执行器的 IP 列表,它会通过比较执行器注册的时间和当前时间,判断该机器是否长期未注册并已下线。由于机器时间滞后,导致该执行器被误判为已下线,因此在测试环境中无法看到新启动的执行器。
2. 失败的任务不间断重试,阻塞正常任务调度
XXL-Job 会把失败的调度任务记录在 xxl-job-callback.log 文件中,并 每隔 30 秒重试一次。如果任务始终未成功,重试将不会结束。
相关代码可以查看 TriggerCallbackThread 和 AdminBizImpl 两个类。
在实际生产环境中,曾遇到 某个调度任务的 HandleCallbackParam.getExecuteResult() 方法返回 null,导致该任务不断重试,阻塞了其他正常任务的调度。最终只能 删除 xxl-job-callback.log 文件 临时解决该问题。
3. 页面日志错误显示了其他任务的日志信息
在 XXL-Job 的执行器中,可以通过 XxlJobLogger.log() 方法打印日志,这样在管理页面上就能查看任务的执行情况。但是如果任务中 使用了异步线程池,那么 日志可能不会正确归属于当前任务的执行日志文件,导致页面显示了其他任务的日志信息。
原因分析
XXL-Job 在 XxlJobFileAppender 类中使用了 线程变量 contextHolder 来存储当前线程的日志文件名。当任务使用线程池执行时,子线程不会继承 contextHolder 变量,因此日志可能会被记录到错误的任务日志文件中。
解决方案
可以通过 将 contextHolder 变量作为参数传递给子线程 来解决此问题。最简单的方法是在子线程开始时 调用 set() 方法设置日志文件名,在子线程结束后 调用 remove() 方法清理变量,确保日志正确归属到当前任务的执行日志中。