Spring Scheduler 无法在 google cloud 中运行且 cpu 节流关闭

Aye*_*era 1 spring-batch spring-scheduled spring-boot google-cloud-platform google-cloud-run

大家好,我有一个正在运行的春季调度程序作业,它必须在谷歌云上运行,并按预定的时间间隔运行。

它与 docker-compose 本地部署完美配合。它会毫无问题地触发。

虽然它在谷歌云运行服务中本地工作正常,并且 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"]
Run Code Online (Sandbox Code Playgroud)

以下是用于部署的 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"
  }
}
Run Code Online (Sandbox Code Playgroud)

我在日志本身中注意到的一些东西

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.
Run Code Online (Sandbox Code Playgroud)

它正在关闭实体管理器。我提供了 -Xmx1024m 堆内存以确保它有足够的内存。

尽管在谷歌文档中提到它应该可以工作,但我不确定由于某种原因调度程序没有被触发。任何帮助都会非常好。

gui*_*ere 6

TL;DR:在 Cloud Run 上使用 Spring Scheduler 是一个坏主意。更喜欢云调度程序

事实上,您必须了解 Cloud Run 实例的生命周期是什么。首先,只有在处理请求时,CPU 才会分配给进程。

其直接影响是后台进程(如调度程序)无法工作,因为没有为请求处理分配 CPU。

除非您将 CPU 限制设置为关闭。你做到了?是的,很棒,但还有其他注意事项!

当请求到来时就会创建一个实例,并且在不处理任何请求的情况下最多可以存活 15 分钟。然后实例被卸载并且缩放到 0。

同样,如果实例关闭,调度程序将无法工作。解决方案是将最小实例设置为 1 并且将 CPU 限制设置为 false,以保持 1 个实例 100% 运行并让调度程序完成其工作。

Cloud Run 的最后一个问题是可扩展性。您在 terraform 中设置 4,这意味着您最多可以有 4 个并行实例,因此有 4 个调度程序并行运行,每个实例上有一个。这真的是你想要的吗?如果没有,您可以将 max instance 设置为 1,以将并行实例的数量限制为 1。


最后,您有 1 个实例,全职运行,并且无法纵向扩展。因为它无法扩展,所以我不建议您在当前实例上执行处理,而是调用在另一个 Cloud Run 实例上运行的另一个 API,该 API 将能够根据调度程序要求进行扩展和缩减。

因此,您将只有 1 个调度程序来对另一个 Cloud Run 服务执行 API 调用来执行任务。这就是云调度程序的目的。