在 App Engine 柔性环境中创建 Java 应用

区域 ID

REGION_ID 是 Google 根据您在创建应用时选择的区域分配的缩写代码。此代码不对应于国家/地区或省,尽管某些区域 ID 可能类似于常用国家/地区代码和省代码。对于 2020 年 2 月以后创建的应用,REGION_ID.r 包含在 App Engine 网址中。对于在此日期之前创建的现有应用,网址中的区域 ID 是可选的。

详细了解区域 ID

本快速入门演示了如何创建和部署一个显示简短消息的应用。示例应用使用 Java 17 版。

GitHub 中提供了 Java 8 版11 版的代码示例。

准备工作

本快速入门假定您已在本地机器上安装 Java SE 17 开发工具包 (JDK)
  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.

    Go to project selector

  3. Make sure that billing is enabled for your Google Cloud project.

  4. Enable the Cloud Build API.

    Enable the API

  5. Install the Google Cloud CLI.
  6. To initialize the gcloud CLI, run the following command:

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

    Go to project selector

  8. Make sure that billing is enabled for your Google Cloud project.

  9. Enable the Cloud Build API.

    Enable the API

  10. Install the Google Cloud CLI.
  11. To initialize the gcloud CLI, run the following command:

    gcloud init

其他前提条件

  1. 初始化您的项目的 App Engine 应用并选择应用的区域:

    gcloud app create --project=[YOUR_PROJECT_ID]
    

    系统提示时,选择您希望自己的 App Engine 应用所在的区域

  2. 安装以下必备组件:

App Engine 位置

App Engine 是区域级的,这意味着运行您的应用的基础架构位于特定区域并由 Google 代管,以使其在该区域内的所有可用区以冗余方式提供。

选择要在哪个区域运行应用时,首先要考虑该区域是否能满足您的延迟时间、可用性或耐用性要求。通常,您可以选择距离应用的用户最近的地区,但也要考虑提供 App Engine 的位置以及应用使用的其他 Google Cloud 产品和服务的位置。跨多个位置使用服务可能会影响应用的延迟时间及其价格

应用的区域一经设置,便无法更改。

如果您已创建 App Engine 应用,则可以通过执行以下任一操作来查看其区域:

下载 Hello World 应用

我们创建了一个 App Engine 版 Hello World 应用,以便您快速了解如何将应用部署到 Google Cloud。

  1. 将 Hello World 示例应用代码库克隆到本地机器。

    git clone https://github.com/GoogleCloudPlatform/java-docs-samples
    

    或者,您也可以下载该示例的 zip 文件并将其解压缩。

  2. 切换到包含示例代码的目录。

       cd java-docs-samples/flexible/java-17/micronaut-helloworld
    

在本地机器上运行 Hello World

如需在本地机器上运行 Hello World 应用,请执行以下操作:

  1. 运行以下命令:
    java -jar target/micronaut-helloworld-0.1.jar
  2. 在网络浏览器中输入以下地址:

    http://localhost:8080

    如果您使用的是 Cloud Shell,请改为在工具栏中点击网页预览,然后选择在端口 8080 上预览

页面中随即显示示例应用发出的 Hello World 消息。在终端窗口中,按 Ctrl+C 退出 Web 服务器。

在 App Engine 上部署并运行 Hello World

要将应用部署到 App Engine 柔性环境,请执行以下操作:

  1. java-17/micronaut-helloworld 目录运行以下命令来部署 Hello World 应用:

    mvn clean package appengine:deploy
  2. 启动浏览器,然后访问 https://PROJECT_ID.REGION_ID.r.appspot.com 以查看此应用

    gcloud app browse
    其中,PROJECT_ID 表示您的 Google Cloud 项目 ID。

这一次,显示 Hello World 消息的页面由在 App Engine 实例上运行的 Web 服务器提供。

恭喜!您已将第一个 App Engine 应用部署到 App Engine 柔性环境!

如果您在部署应用时遇到任何错误,请查看问题排查提示

如需了解有关清理的信息以及可执行的后续步骤的链接,请参阅以下部分。

清理

为避免产生费用,您可以删除 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.

后续步骤

了解整个平台

现在,您已了解如何开发和部署 App Engine 应用,接下来您可以探索 Google Cloud 的其余部分。您已经安装了 Google Cloud CLI,它可为您提供与 Cloud SQL、Cloud Storage、Firestore 等产品交互的工具。

了解 App Engine 柔性环境

以下主题有助于您继续了解 App Engine:

Hello World 代码审核

Hello World 是最简单的 App Engine 应用,因为它只包含一项服务,只有一个版本,并且所有代码都位于应用的根目录中。本部分详细介绍了各应用文件。

HelloControllerTest.java

HelloControllerTest.java 文件指定了一个网址模式,用于说明应用将侦听请求的位置,并使用“Hello World”消息响应任何请求。

/*
 * Copyright 2023 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.
 */

package com.example.appengine;

import static org.junit.Assert.assertEquals;

import io.micronaut.context.ApplicationContext;
import io.micronaut.http.HttpRequest;
import io.micronaut.http.client.HttpClient;
import io.micronaut.runtime.server.EmbeddedServer;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;

public class HelloControllerTest {
  private static EmbeddedServer server;
  private static HttpClient client;

  @BeforeClass
  public static void setupServer() {

    server = ApplicationContext.run(EmbeddedServer.class);

    client = server.getApplicationContext().createBean(HttpClient.class, server.getURL());
  }

  @AfterClass
  public static void stopServer() {
    if (client != null) {
      client.stop();
    }
    if (server != null) {
      server.stop();
    }
  }

  @Test
  public void testHelloWorldResponse() {
    String response = client.toBlocking().retrieve(HttpRequest.GET("/"));
    assertEquals("Hello World!", response);
  }
}

app.yaml

app.yaml 文件描述了应用的以下配置:

  • 设置 env: flex,以指示您的应用使用 App Engine 柔性环境
  • 指定应用使用的运行时。

    runtime: java
    env: flex
    runtime_config:
      operating_system: ubuntu22
      runtime_version: 17
    handlers:
    - url: /.*
      script: this field is required, but ignored
    
    manual_scaling:
      instances: 1
    • 如需详细了解 Java 运行时的工作原理,请参阅 Java 运行时

    pom.xml

    Hello World 还包含一个 pom.xml 文件,其中包含有关项目的信息,例如其依赖项和构建目标。

    <?xml version="1.0" encoding="UTF-8"?>
    <!--
      Copyright 2023 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.appengine.flexible</groupId>
      <artifactId>micronaut-helloworld</artifactId>
      <version>0.1</version>
    
      <!--
      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>
        <exec.mainClass>com.example.appengine.Application</exec.mainClass>
        <maven.compiler.target>11</maven.compiler.target>
        <maven.compiler.source>11</maven.compiler.source>
        <micronaut.version>3.10.3</micronaut.version>
      </properties>
    
      <dependencies>
        <dependency>
          <groupId>io.micronaut</groupId>
          <artifactId>micronaut-inject</artifactId>
          <version>${micronaut.version}</version>
          <scope>compile</scope>
        </dependency>
        <dependency>
          <groupId>io.micronaut</groupId>
          <artifactId>micronaut-validation</artifactId>
          <version>${micronaut.version}</version>
          <scope>compile</scope>
        </dependency>
        <dependency>
          <groupId>io.micronaut</groupId>
          <artifactId>micronaut-runtime</artifactId>
          <version>${micronaut.version}</version>
          <scope>compile</scope>
        </dependency>
        <dependency>
          <groupId>io.micronaut</groupId>
          <artifactId>micronaut-http-client</artifactId>
          <version>${micronaut.version}</version>
          <scope>compile</scope>
        </dependency>
        <dependency>
          <groupId>javax.annotation</groupId>
          <artifactId>javax.annotation-api</artifactId>
          <version>1.3.2</version>
          <scope>compile</scope>
        </dependency>
        <dependency>
          <groupId>io.micronaut</groupId>
          <artifactId>micronaut-http-server-netty</artifactId>
          <version>${micronaut.version}</version>
          <scope>compile</scope>
        </dependency>
        <dependency>
          <groupId>junit</groupId>
          <artifactId>junit</artifactId>
          <version>4.13.2</version>
          <scope>test</scope>
        </dependency>
      </dependencies>
    
      <build>
        <plugins>
          <plugin>
            <groupId>com.google.cloud.tools</groupId>
            <artifactId>appengine-maven-plugin</artifactId>
            <version>2.8.0</version>
            <configuration>
              <projectId>GCLOUD_CONFIG</projectId>
              <version>micronaut-helloworld</version>
            </configuration>
          </plugin>
          <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-shade-plugin</artifactId>
            <version>3.5.1</version>
            <executions>
              <execution>
                <phase>package</phase>
                <goals>
                  <goal>shade</goal>
                </goals>
                <configuration>
                  <transformers>
                    <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                      <mainClass>${exec.mainClass}</mainClass>
                    </transformer>
                    <transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/>
                  </transformers>
                </configuration>
              </execution>
            </executions>
          </plugin>
          <plugin>
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>exec-maven-plugin</artifactId>
            <version>3.1.1</version>
            <configuration>
              <executable>java</executable>
              <arguments>
                <argument>-noverify</argument>
                <argument>-XX:TieredStopAtLevel=1</argument>
                <argument>-Dcom.sun.management.jmxremote</argument>
                <argument>-classpath</argument>
                <classpath/>
                <argument>${exec.mainClass}</argument>
              </arguments>
            </configuration>
          </plugin>
          <plugin>
            <artifactId>maven-surefire-plugin</artifactId>
            <version>3.2.5</version>
          </plugin>
    
            <plugin>
              <groupId>org.apache.maven.plugins</groupId>
              <artifactId>maven-compiler-plugin</artifactId>
              <version>3.12.1</version>
              <configuration>
                <encoding>UTF-8</encoding>
                <compilerArgs>
                  <arg>-parameters</arg>
                </compilerArgs>
                <annotationProcessorPaths>
                  <path>
                    <groupId>io.micronaut</groupId>
                    <artifactId>micronaut-inject-java</artifactId>
                    <version>${micronaut.version}</version>
                  </path>
                  <path>
                    <groupId>io.micronaut</groupId>
                    <artifactId>micronaut-validation</artifactId>
                    <version>${micronaut.version}</version>
                  </path>
                </annotationProcessorPaths>
              </configuration>
              <executions>
                <execution>
                  <id>test-compile</id>
                  <goals>
                    <goal>testCompile</goal>
                  </goals>
                  <configuration>
                    <compilerArgs>
                      <arg>-parameters</arg>
                    </compilerArgs>
                    <annotationProcessorPaths>
                      <path>
                        <groupId>io.micronaut</groupId>
                        <artifactId>micronaut-inject-java</artifactId>
                        <version>${micronaut.version}</version>
                      </path>
                      <path>
                        <groupId>io.micronaut</groupId>
                        <artifactId>micronaut-validation</artifactId>
                        <version>${micronaut.version}</version>
                      </path>
                    </annotationProcessorPaths>
                  </configuration>
                </execution>
              </executions>
            </plugin>
          </plugins>
    
      </build>
    </project>
    
    • 如需详细了解 pom.xml 文件,请参阅 Maven 文档