Spring 调度程序无法在 google 云 运行 中工作,cpu 节流
Spring Scheduler not working in google cloud run with cpu throttling off
你好,我有一个 spring 调度程序作业 运行ning,它必须在 google 云 运行 上 运行 并具有预定的时间间隔。
它与 docker-compose 本地部署完美配合。它被触发没有任何问题。
虽然它在 google 云 运行 服务中本地运行良好,但 CPU 节流关闭,这使得 CPU 始终保持 100% 开启,但在第一个 运行.
我将粘贴 docker 文件供任何一次参考,但我很确定它工作正常
FROM maven:3-jdk-11-slim AS build-env
# Set the working directory to /app
WORKDIR /app
COPY pom.xml ./
COPY src ./src
COPY css-common ./css-common
RUN echo $(ls -1 css-common/src/main/resources)
# Build and create the common jar
RUN cd css-common && mvn clean install
# Build and the job
RUN mvn package -DskipTests
# It's important to use OpenJDK 8u191 or above that has container support enabled.
# https://docs.docker.com/develop/develop-images/multistage-build/#use-multi-stage-builds
FROM openjdk:11-jre-slim
# Copy the jar to the production image from the builder stage.
COPY --from=build-env /app/target/css-notification-job-*.jar /app.jar
# Run the web service on container startup
CMD ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]
下面是用于部署的 terraform 脚本
resource "google_cloud_run_service" "job-staging" {
name = var.cloud_run_job_name
project = var.project
location = var.region
template {
spec {
containers {
image = "${var.docker_registry}/${var.project}/${var.cloud_run_job_name}:${var.docker_tag_notification_job}"
env {
name = "DB_HOST"
value = var.host
}
env {
name = "DB_PORT"
value = 3306
}
}
}
metadata {
annotations = {
"autoscaling.knative.dev/maxScale" = "4"
"run.googleapis.com/vpc-access-egress" = "all-traffic"
"run.googleapis.com/cpu-throttling" = false
}
}
}
timeouts {
update = "3m"
}
}
我在日志中注意到的一些事情
2022-01-04T00:19:39.178057Z2022-01-04 00:19:39.177 INFO 1 --- [ionShutdownHook] j.LocalContainerEntityManagerFactoryBean : Closing JPA EntityManagerFactory for persistence unit 'default'
Standard
2022-01-04T00:19:39.182017Z2022-01-04 00:19:39.181 INFO 1 --- [ionShutdownHook] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Shutdown initiated...
Standard
2022-01-04T00:19:39.194117Z2022-01-04 00:19:39.193 INFO 1 --- [ionShutdownHook] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Shutdown completed.
正在关闭实体管理器。我提供了 -Xmx1024m 堆内存以确保它有足够的内存。
虽然在 google 文档中提到它应该可以工作,但由于某种原因我不确定调度程序是否被触发。任何帮助都会非常好。
TL;DR:在云 运行 上使用 Spring 调度器不是一个好主意。改用 Cloud Scheduler
其实你要明白什么是云运行实例的生命周期。首先,CPU仅在处理请求时分配给进程。
这样做的直接影响是后台进程(如调度程序)无法工作,因为没有 CPU 分配给请求处理。
除非您将 CPU 节流设置为关闭。你做到了?是的,很好,但还有其他注意事项!
一个实例在收到请求时创建,并在没有任何请求处理的情况下存活长达 15 分钟。然后实例被卸载,你扩展到 0.
同样,如果实例关闭,调度程序将无法工作。解决方案是将最小实例设置为 1 并将 CPU 节流设置为 false 以保持 1 个实例 100% 运行并让调度程序完成其工作。
Cloud 运行 的最后一个问题是可扩展性。您在 terraform 中设置了 4,这意味着您最多可以并行运行 4 个实例,因此并行运行 4 个调度程序 运行ning,每个实例一个。这真的是你想要的吗?如果没有,你可以设置max instance为1来限制parallel instance的个数为1。
最后,您有 1 个实例,全时运行,并且无法向上和向下扩展。因为它不能扩展,我不建议你在当前实例上执行处理,而是调用另一个 API which 运行 on another Cloud 运行 instance and that will be able to根据调度程序要求扩大和缩小规模。
因此,您将只有 1 个调度程序将执行 API 调用另一个云 运行 服务来执行任务。这就是 Cloud Scheduler 的目的。
你好,我有一个 spring 调度程序作业 运行ning,它必须在 google 云 运行 上 运行 并具有预定的时间间隔。
它与 docker-compose 本地部署完美配合。它被触发没有任何问题。
虽然它在 google 云 运行 服务中本地运行良好,但 CPU 节流关闭,这使得 CPU 始终保持 100% 开启,但在第一个 运行.
我将粘贴 docker 文件供任何一次参考,但我很确定它工作正常
FROM maven:3-jdk-11-slim AS build-env
# Set the working directory to /app
WORKDIR /app
COPY pom.xml ./
COPY src ./src
COPY css-common ./css-common
RUN echo $(ls -1 css-common/src/main/resources)
# Build and create the common jar
RUN cd css-common && mvn clean install
# Build and the job
RUN mvn package -DskipTests
# It's important to use OpenJDK 8u191 or above that has container support enabled.
# https://docs.docker.com/develop/develop-images/multistage-build/#use-multi-stage-builds
FROM openjdk:11-jre-slim
# Copy the jar to the production image from the builder stage.
COPY --from=build-env /app/target/css-notification-job-*.jar /app.jar
# Run the web service on container startup
CMD ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]
下面是用于部署的 terraform 脚本
resource "google_cloud_run_service" "job-staging" {
name = var.cloud_run_job_name
project = var.project
location = var.region
template {
spec {
containers {
image = "${var.docker_registry}/${var.project}/${var.cloud_run_job_name}:${var.docker_tag_notification_job}"
env {
name = "DB_HOST"
value = var.host
}
env {
name = "DB_PORT"
value = 3306
}
}
}
metadata {
annotations = {
"autoscaling.knative.dev/maxScale" = "4"
"run.googleapis.com/vpc-access-egress" = "all-traffic"
"run.googleapis.com/cpu-throttling" = false
}
}
}
timeouts {
update = "3m"
}
}
我在日志中注意到的一些事情
2022-01-04T00:19:39.178057Z2022-01-04 00:19:39.177 INFO 1 --- [ionShutdownHook] j.LocalContainerEntityManagerFactoryBean : Closing JPA EntityManagerFactory for persistence unit 'default'
Standard
2022-01-04T00:19:39.182017Z2022-01-04 00:19:39.181 INFO 1 --- [ionShutdownHook] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Shutdown initiated...
Standard
2022-01-04T00:19:39.194117Z2022-01-04 00:19:39.193 INFO 1 --- [ionShutdownHook] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Shutdown completed.
正在关闭实体管理器。我提供了 -Xmx1024m 堆内存以确保它有足够的内存。
虽然在 google 文档中提到它应该可以工作,但由于某种原因我不确定调度程序是否被触发。任何帮助都会非常好。
TL;DR:在云 运行 上使用 Spring 调度器不是一个好主意。改用 Cloud Scheduler
其实你要明白什么是云运行实例的生命周期。首先,CPU仅在处理请求时分配给进程。
这样做的直接影响是后台进程(如调度程序)无法工作,因为没有 CPU 分配给请求处理。
除非您将 CPU 节流设置为关闭。你做到了?是的,很好,但还有其他注意事项!
一个实例在收到请求时创建,并在没有任何请求处理的情况下存活长达 15 分钟。然后实例被卸载,你扩展到 0.
同样,如果实例关闭,调度程序将无法工作。解决方案是将最小实例设置为 1 并将 CPU 节流设置为 false 以保持 1 个实例 100% 运行并让调度程序完成其工作。
Cloud 运行 的最后一个问题是可扩展性。您在 terraform 中设置了 4,这意味着您最多可以并行运行 4 个实例,因此并行运行 4 个调度程序 运行ning,每个实例一个。这真的是你想要的吗?如果没有,你可以设置max instance为1来限制parallel instance的个数为1。
最后,您有 1 个实例,全时运行,并且无法向上和向下扩展。因为它不能扩展,我不建议你在当前实例上执行处理,而是调用另一个 API which 运行 on another Cloud 运行 instance and that will be able to根据调度程序要求扩大和缩小规模。
因此,您将只有 1 个调度程序将执行 API 调用另一个云 运行 服务来执行任务。这就是 Cloud Scheduler 的目的。