我正在使用 groovy 和 gradle 开发一个现有的 micronaut 应用程序,它有一个调度程序,预计每 1 分钟运行一次。不知何故,调度程序根本不运行,应用程序也没有抛出任何错误(只是保持沉默)。我看不出有任何理由不应该这样做,但我是 micronaut 的新手,我可能会遗漏一些东西。感谢任何指针,从很长一段时间以来一直困扰着这个问题。 这里是调度类。
@CompileStatic
@Singleton
@Requires(notEnv = "test")
class CsmTestJob {
private final CsmTestJobExecutor csmTestJobExecutor
CsmTestJob(CsmTestJobExecutor csmTestJobExecutor) {
this.csmTestJobExecutor = csmTestJobExecutor
}
@Scheduled(fixedDelay = '${feature.job.execute}')
void executeCsmTests() {
csmTestJobExecutor.executeCsmTests()
}
}
这是
application.yml
文件
micronaut:
application:
name: csm
server:
port: 8080
host: 127.0.0.1
feature:
job:
execute: "1m"
我在 AWS Docker (EC2 Amazon) 中运行 Micronaut 时遇到了这个问题(我认为也可以在 1 个核心 CPU 上重现)
研究成果:
在带有选项
@Scheduler
的Docker中使用
--cpus 1
重现运行应用程序
docker run --cpus 1 microscheduleapp
看起来 Micronaut 在启动时依赖于 ForkJoinPool,但如果你有超过 1 个 CPU 内核,默认的 ForkJoinPool 将工作。在这种情况下,Micronaut 无法实例化预定服务。 但是手动启动的计划任务工作正常。
修复使用 ForkJoinPool 并行选项以允许池大于 CPU:
java -Djava.util.concurrent.ForkJoinPool.common.parallelism=4 -jar application.jar
有关于删除静态编译和删除动态调度值的评论,但我认为这两者都不太可能相关。问题中显示的代码不足,无法确定,但我怀疑您的代码可能使用了错误的
@Singleton
注释。
查看项目https://github.com/jeffbrown/nilambersinghscheduledjob.
micronaut:
application:
name: nilambersinghscheduledjob
feature:
job:
execute: "1m"
package com.example
import groovy.transform.CompileStatic
import io.micronaut.context.annotation.Requires
import io.micronaut.scheduling.annotation.Scheduled
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import javax.inject.Singleton
@CompileStatic
@Singleton
@Requires(notEnv = "test")
class CsmTestJob {
private static final Logger log = LoggerFactory.getLogger(CsmTestJob)
@Scheduled(fixedDelay = '${feature.job.execute}')
void executeCsmTests() {
log.debug "CSM Test Job Is Running"
}
}
一切正常。
不久前我遇到了类似的问题,结果证明我在课堂上的其他注释之一以某种方式干扰并阻止了调度程序运行。
我会尝试删除 CompileStatic 并将计划硬编码为直接字符串文字。
还要确保您正在导入
javax.inject.Singleton
,否则您对 Singleton
的引用将选择 groovy 默认值 groovy.lang.Singleton
,这将破坏 micronaut 机制。
最后要尝试的是打开调试日志记录并阅读 micronaut 打印的大量信息。就我而言,我可以从调试日志中看到 bean 初始化存在问题。
我意识到这不是一个直接的解决方案,但我认为提供一些潜在的建议总比什么都不提供要好。
我们在 AWS 上的 Kubernetes 中运行的 Micronaut 3.8.4 也遇到了同样的情况。 该问题与 java 17 bug 有关。基本上,就像@Dmitry 所说的那样,ForkJoinPool 不适用于 1 个核心。该错误已在 jdk 19 中解决。
升级 DockerFile 以使用 openjdk:19-alpine 解决了问题而无需更改属性-Djava.util.concurrent.ForkJoinPool.common.parallelism