在 Cloud Run 中构建和创建 Java 作业

了解如何创建简单的 Cloud Run 作业,然后从源代码进行部署,以自动将代码打包到容器映像中,将容器映像上传到 Artifact Registry,接着部署到 Cloud Run。除了所示语言之外,您还可以使用其他语言。

准备工作

  1. Sign in to your Google Cloud account. If you're new to Google Cloud, create an account to evaluate how our products perform in real-world scenarios. New customers also get $300 in free credits to run, test, and deploy workloads.
  2. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Roles required to select or create a project

    • Select a project: Selecting a project doesn't require a specific IAM role—you can select any project that you've been granted a role on.
    • Create a project: To create a project, you need the Project Creator (roles/resourcemanager.projectCreator), which contains the resourcemanager.projects.create permission. Learn how to grant roles.

    Go to project selector

  3. Verify that billing is enabled for your Google Cloud project.

  4. Install the Google Cloud CLI.

  5. 如果您使用的是外部身份提供方 (IdP),则必须先使用联合身份登录 gcloud CLI

  6. 如需初始化 gcloud CLI,请运行以下命令:

    gcloud init
  7. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Roles required to select or create a project

    • Select a project: Selecting a project doesn't require a specific IAM role—you can select any project that you've been granted a role on.
    • Create a project: To create a project, you need the Project Creator (roles/resourcemanager.projectCreator), which contains the resourcemanager.projects.create permission. Learn how to grant roles.

    Go to project selector

  8. Verify that billing is enabled for your Google Cloud project.

  9. Install the Google Cloud CLI.

  10. 如果您使用的是外部身份提供方 (IdP),则必须先使用联合身份登录 gcloud CLI

  11. 如需初始化 gcloud CLI,请运行以下命令:

    gcloud init
  12. Enable the Cloud Run Admin API and Cloud Build APIs.

    Roles required to enable APIs

    To enable APIs, you need the Service Usage Admin IAM role (roles/serviceusage.serviceUsageAdmin), which contains the serviceusage.services.enable permission. Learn how to grant roles.

    Enable the APIs

    启用 Cloud Run Admin API 后,系统会自动创建 Compute Engine 默认服务账号。

  13. 点击可查看 Cloud Build 服务账号需要的角色

    除非您替换此行为,否则 Cloud Build 会自动使用 Compute Engine 默认服务账号作为默认 Cloud Build 服务账号来构建源代码和 Cloud Run 资源。为了让 Cloud Build 能够构建来源,请让管理员向项目的 Compute Engine 默认服务账号授予 Cloud Run Builder (roles/run.builder):

      gcloud projects add-iam-policy-binding PROJECT_ID \
          --member=serviceAccount:PROJECT_NUMBER-compute@developer.gserviceaccount.com \
          --role=roles/run.builder
      

    PROJECT_NUMBER 替换为您的 Google Cloud项目编号,将 PROJECT_ID 替换为您的 Google Cloud项目 ID。如需详细了解如何查找项目 ID 和项目编号,请参阅创建和管理项目

    向 Compute Engine 默认服务账号授予 Cloud Run Builder 角色需要几分钟时间才能传播

  14. 查看 Cloud Run 价格或使用价格计算器估算费用。
  15. 编写示例作业

    如需使用 Java 编写作业,请执行以下操作:

    1. 创建名为 jobs 的新目录,并转到此目录中:

      mkdir jobs
      cd jobs
      
    2. 在名为 src/main/java/com/example 的子目录中,为实际作业代码创建一个 JobsExample.java 文件。将以下示例行复制到其中:

      
      package com.example;
      
      abstract class JobsExample {
        // These values are provided automatically by the Cloud Run Jobs runtime.
        private static String CLOUD_RUN_TASK_INDEX =
            System.getenv().getOrDefault("CLOUD_RUN_TASK_INDEX", "0");
        private static String CLOUD_RUN_TASK_ATTEMPT =
            System.getenv().getOrDefault("CLOUD_RUN_TASK_ATTEMPT", "0");
      
        // User-provided environment variables
        private static int SLEEP_MS = Integer.parseInt(System.getenv().getOrDefault("SLEEP_MS", "0"));
        private static float FAIL_RATE =
            Float.parseFloat(System.getenv().getOrDefault("FAIL_RATE", "0.0"));
      
        // Start script
        public static void main(String[] args) {
          System.out.println(
              String.format(
                  "Starting Task #%s, Attempt #%s...", CLOUD_RUN_TASK_INDEX, CLOUD_RUN_TASK_ATTEMPT));
          try {
            runTask(SLEEP_MS, FAIL_RATE);
          } catch (RuntimeException | InterruptedException e) {
            System.err.println(
                String.format(
                    "Task #%s, Attempt #%s failed.", CLOUD_RUN_TASK_INDEX, CLOUD_RUN_TASK_ATTEMPT));
            // Catch error and denote process-level failure to retry Task
            System.exit(1);
          }
        }
      
        static void runTask(int sleepTime, float failureRate) throws InterruptedException {
          // Simulate work
          if (sleepTime > 0) {
            Thread.sleep(sleepTime);
          }
      
          // Simulate errors
          if (failureRate < 0 || failureRate > 1) {
            System.err.println(
                String.format(
                    "Invalid FAIL_RATE value: %s. Must be a float between 0 and 1 inclusive.",
                    failureRate));
            return;
          }
          if (Math.random() < failureRate) {
            throw new RuntimeException("Task Failed.");
          }
          System.out.println(String.format("Completed Task #%s", CLOUD_RUN_TASK_INDEX));
        }
      }

      Cloud Run 作业允许用户指定作业要执行的任务数量。此示例代码演示了如何使用内置 CLOUD_RUN_TASK_INDEX 环境变量。每个任务代表容器的一个正在运行的副本。 请注意,任务通常并行执行。如果每个任务都可以独立处理一部分数据,则使用多个任务非常有用。

      每个任务都知道其存储在 CLOUD_RUN_TASK_INDEX 环境变量中的索引。内置 CLOUD_RUN_TASK_COUNT 环境变量包含在执行作业时通过 --tasks 参数提供的任务数量。

      此处所示的代码还展示了如何使用内置 CLOUD_RUN_TASK_ATTEMPT 环境变量重试任务,该变量包含此任务重试的次数,从 0 开始(表示第一次尝试),然后每次连续重试时递增 1,上限为 --max-retries

      此外,通过代码,您还可以生成失败来测试重试并生成错误日志,从而查看失败情况。

    3. 创建一个包含以下内容的 pom.xml 文件:

      <?xml version="1.0" encoding="UTF-8"?>
      <!--
      Copyright 2021 Google LLC
      Licensed under the Apache License, Version 2.0 (the "License");
      you may not use this file except in compliance with the License.
      You may obtain a copy of the License at
      http://www.apache.org/licenses/LICENSE-2.0
      Unless required by applicable law or agreed to in writing, software
      distributed under the License is distributed on an "AS IS" BASIS,
      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      See the License for the specific language governing permissions and
      limitations under the License.
      -->
      <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
        <groupId>com.example.run</groupId>
        <artifactId>jobs-example</artifactId>
        <version>0.0.1</version>
        <packaging>jar</packaging>
      
        <!--  The parent pom defines common style checks and testing strategies for our samples.
      	Removing or replacing it should not affect the execution of the samples in anyway. -->
        <parent>
          <groupId>com.google.cloud.samples</groupId>
          <artifactId>shared-configuration</artifactId>
          <version>1.2.0</version>
        </parent>
      
        <properties>
          <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
          <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
          <maven.compiler.target>17</maven.compiler.target>
          <maven.compiler.source>17</maven.compiler.source>
        </properties>
      
        <dependencyManagement>
          <dependencies>
            <dependency>
              <artifactId>libraries-bom</artifactId>
              <groupId>com.google.cloud</groupId>
              <scope>import</scope>
              <type>pom</type>
              <version>26.32.0</version>
            </dependency>
          </dependencies>
        </dependencyManagement>
      
        <dependencies>
          <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13.2</version>
            <scope>test</scope>
          </dependency>
          <dependency>
            <groupId>com.google.truth</groupId>
            <artifactId>truth</artifactId>
            <version>1.4.0</version>
            <scope>test</scope>
          </dependency>
          <dependency>
            <groupId>com.google.cloud</groupId>
            <artifactId>google-cloud-logging</artifactId>
            <scope>test</scope>
          </dependency>
        </dependencies>
      
        <build>
          <plugins>
            <plugin>
              <groupId>org.apache.maven.plugins</groupId>
              <artifactId>maven-jar-plugin</artifactId>
              <version>3.3.0</version>
              <configuration>
                <archive>
                  <manifest>
                    <addClasspath>true</addClasspath>
                    <mainClass>com.example.JobsExample</mainClass>
                  </manifest>
                </archive>
              </configuration>
            </plugin>
          </plugins>
        </build>
      </project>
      
    4. 创建一个包含以下内容的 project.toml 文件,以使用 Buildpack 支持的 Java 版本进行构建:

      # Default version is Java 11
      #  - See https://cloud.google.com/docs/buildpacks/java#specify_a_java_version
      # Match the version required in pom.xml by setting it here
      #  - See https://cloud.google.com/docs/buildpacks/set-environment-variables#build_the_application_with_environment_variables
      
      [[build.env]]
        name = "GOOGLE_RUNTIME_VERSION"
        value = "17"
      

    您的代码已完成,可以封装在容器中。

    构建作业容器,将其发送到 Artifact Registry 并部署到 Cloud Run

    重要提示:本快速入门假定您在快速入门中使用的项目中拥有所有者或编辑者角色。否则,请参阅 Cloud Run Source Developer 角色,了解从源代码部署 Cloud Run 资源所需的权限。

    本快速入门使用“从源代码部署”,以构建容器,将其上传到 Artifact Registry,然后将作业部署到 Cloud Run:

    gcloud run jobs deploy job-quickstart \
        --source . \
        --tasks 50 \
        --set-env-vars SLEEP_MS=10000 \
        --set-env-vars FAIL_RATE=0.1 \
        --max-retries 5 \
        --region REGION \
        --project=PROJECT_ID

    其中,PROJECT_ID 是您的项目 ID,REGION 是您的区域,例如 europe-west1。请注意,您可以将各种参数更改为要用于测试的任何值。SLEEP_MS 模拟工作,FAIL_RATE 导致 X% 的任务失败,因此您可以试验并行情况并重试失败任务。

    在 Cloud Run 中执行作业

    如需执行刚刚创建的作业,请运行以下命令:

    gcloud run jobs execute job-quickstart --region REGION

    REGION 替换为您在创建和部署作业时使用的区域,例如 europe-west1

    清理

    为避免您的 Google Cloud 账号产生额外费用,请删除您在本快速入门中部署的所有资源。

    删除仓库

    Cloud Run 仅针对作业的执行时间收费。不过,您可能仍需要支付将容器映像存储在 Artifact Registry 中而产生的相关费用。如需删除 Artifact Registry 仓库,请按照 Artifact Registry 文档中删除仓库的步骤操作。

    删除作业

    Cloud Run 作业仅在作业任务执行时产生费用。如需删除 Cloud Run 作业,请按照以下步骤之一操作:

    控制台

    要删除任务,请执行以下操作:

    1. 在 Google Cloud 控制台中,前往 Cloud Run:

      转到 Cloud Run

    2. 在作业列表中找到要删除的作业,然后点击该作业对应的复选框以将其选中。

    3. 点击删除。这会终止所有正在进行的作业执行和所有正在运行的容器实例。

    gcloud

    要删除作业,请运行以下命令:

    gcloud run jobs delete JOB_NAME

    JOB_NAME 替换为作业的名称。

    删除测试项目

    删除 Google Cloud 项目后,系统即会停止对该项目中的所有资源计费。如需释放项目中的所有 Google Cloud 资源,请按照以下步骤操作:

    1. In the Google Cloud console, go to the Manage resources page.

      Go to Manage resources

    2. In the project list, select the project that you want to delete, and then click Delete.
    3. In the dialog, type the project ID, and then click Shut down to delete the project.

    后续步骤

    如需详细了解如何使用代码源构建容器并推送到仓库,请参阅: