Java 執行階段環境

Java 執行階段是一個軟體堆疊,負責安裝網路服務的程式碼和其依附元件,並執行服務。

app.yaml 檔案中宣告 App Engine 標準環境的 Java 執行階段。例如:

runtime: javaVERSION

其中 VERSION 是 Java MAJOR 版本號碼。舉例來說,如要使用最新的 Java 版本 (Java 25 預先發布版),請指定 25

如要瞭解其他支援的 Java 版本,以及 Java 版本對應的 Ubuntu 版本,請參閱執行階段支援時間表

事前準備

  1. 下載最新版的 Google Cloud CLI,或是將 gcloud CLI 更新至最新版本:

    gcloud components update
    
  2. 如要使用 Maven 進行部署,您必須在 pom.xml 檔案中新增 App Engine Maven 外掛程式

    <plugin>
       <groupId>com.google.cloud.tools</groupId>
       <artifactId>appengine-maven-plugin</artifactId>
       <version>2.8.1</version>
    </plugin>

    其他部署選項包括使用 gcloud app deploy 指令或 App Engine Gradle 外掛程式

  3. 請按照您應用程式架構的操作說明,設定可執行 JAR 檔案的版本。

架構相容性

您可以使用 App Engine Java 執行階段部署可執行的 JAR 檔案。這些執行階段不包含任何網路服務架構,因此您不限於使用以 Servlet 為基礎的架構或程式庫。使用原生依附元件或 Netty 程式庫等網路堆疊。

您不一定要使用這些架構,我們建議您嘗試偏好的架構,例如 Grails、Blade、Play!、Vaadin 或 jHipster

將 Maven 原始碼專案部署至 Java 執行階段

您可以將 Maven 專案部署為原始碼,並使用 Google Cloud 的建構套件建構及部署專案。

如要以原始碼形式部署 Maven 專案,請前往專案的頂層目錄,然後輸入:

gcloud app deploy pom.xml

系統會串流建構和部署記錄,您可以在Google Cloud 控制台的 Cloud Build 記錄部分查看詳細記錄。

使用 GraalVM 可執行檔

App Engine 標準環境 Java 執行階段支援 GraalVM 原生映像檔可執行檔。將 Java 應用程式編譯為 GraalVM 原生映像檔後,您可以使用 app.yaml 檔案中的 entrypoint 設定,指向可執行檔。

舉例來說,如果可執行檔的檔案名稱是 myexecutable,則可能會有下列 app.yaml 設定檔:

runtime: 25 # or another supported runtime version.
entrypoint: ./myexecutable

Google Cloud 用戶端程式庫可用於將應用程式編譯為 GraalVM 原生映像檔。詳情請參閱「編譯原生映像檔」的說明文件。

Java 版本

最新支援的 Java 版本為 25 (預先發布版)。Java 執行階段會使用 app.yaml 檔案中指定版本的最新穩定版。App Engine 會自動更新至新的修補程式版本,但不會自動更新次要版本。

舉例來說,您的應用程式在部署時可能採用了 Java 21.0.4,且在後續的受管理平台部署作業中自動更新到版本 Java 21.0.5,但它並不會自動更新到 Java 22。

如要瞭解如何升級 Java 版本,請參閱「升級現有應用程式」。

執行階段的 Open JDK 環境

App Engine 會在容器中執行 Java 應用程式,並透過最新版 Ubuntu Linux 發行版上的 gVisor 保護容器安全。此外,App Engine 也支援 Java 17 適用的 openjdk-17-jdk,以及 Java 21 執行階段適用的 openjdk-21-jdk。

如要瞭解 Java 版本支援的 Ubuntu 版本,請參閱執行階段支援時間表

App Engine 會維護基礎映像檔,並更新 OpenJDK 17 和 OpenJDK 21 套件,您無須重新部署應用程式。

部署的應用程式位於執行階段的 /workspace 目錄中。您也可以透過 /srv 的符號連結存取。

App Engine Java 版本

所有以版本 2.x.x 開頭的發布構件,都使用開放原始碼發布機制。詳情請參閱 GitHub 存放區

依附元件

如需瞭解如何宣告及管理依附元件,請參閱指定相依元件

啟動應用程式

Spring Boot、Micronaut、Ktor 等架構預設會建構可執行的 uber JAR。如果 Maven 或 Gradle 建構檔案產生可執行的 Uber JAR,執行階段會執行 Uber JAR 應用程式,啟動您的應用程式。

否則,App Engine 會使用 app.yaml 檔案中選用 entrypoint 欄位的內容。例如:

runtime: java25 # or another supported runtime
entrypoint: java -Xmx64m -jar YOUR-ARTIFACT.jar

範例 YOUR-ARTIFACT.jar 應用程式的 Jar 檔必須符合下列條件:

  • 位於根目錄中,與 app.yaml 檔案同層。
  • META-INF/MANIFEST.MF 中繼資料檔案中包含 Main-Class 項目。
  • (選用) 包含 Class-Path 項目,其中列出其他相依 JAR 的相對路徑。這些檔案會自動與應用程式一併上傳。

為了讓應用程式接收 HTTP 要求,entrypoint 應啟動一個網路伺服器,來監聽由 PORT 環境變數指定的通訊埠。PORT 環境變數的值是由 App Engine 服務環境動態設定。這個值無法在 app.yaml 檔案的 env_variables 區段中設定。

使用自訂進入點,您可以將應用程式建構及封裝為精簡的 JAR 檔案,其中只包含應用程式程式碼和直接依附元件。部署應用程式時,App Engine 外掛程式只會上傳變更的檔案,而不是整個 uber JAR 套件。

請務必使用 PORT 環境變數

如果應用程式記錄檔中顯示通訊埠 8080 和 NGINX 的相關警告,表示應用程式的網頁伺服器正在監聽預設通訊埠 8080。這樣一來,App Engine 就無法使用 NGINX 層壓縮 HTTP 回應。建議您將網路伺服器設為回應 PORT 環境變數指定的通訊埠 (通常為 8081) 的 HTTP 要求。例如:

/*
 * Copyright 2019 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 com.sun.net.httpserver.HttpServer;
import java.io.IOException;
import java.io.OutputStream;
import java.net.InetSocketAddress;

public class Main {

  public static void main(String[] args) throws IOException {
    // Create an instance of HttpServer bound to port defined by the 
    // PORT environment variable when present, otherwise on 8080.
    int port = Integer.parseInt(System.getenv().getOrDefault("PORT", "8080"));
    HttpServer server = HttpServer.create(new InetSocketAddress(port), 0);

    // Set root URI path.
    server.createContext("/", (var t) -> {
      byte[] response = "Hello World!".getBytes();
      t.sendResponseHeaders(200, response.length);
      try (OutputStream os = t.getResponseBody()) {
        os.write(response);
      }
    });

    // Create a second URI path.
    server.createContext("/foo", (var t) -> {
      byte[] response = "Foo!".getBytes();
      t.sendResponseHeaders(200, response.length);
      try (OutputStream os = t.getResponseBody()) {
        os.write(response);
      }
    });

    server.start();
  }
}

與舊版 Java 的相容性

如要瞭解 Java 8 與最新支援的 Java 版本之間的差異,請參閱「從 Java 8 遷移至最新 Java 執行階段」。

環境變數

下列為執行階段設定的環境變數:

環境變數 說明
GAE_APPLICATION App Engine 應用程式的 ID。 這個 ID 的前置字元為「region code~」,例如在歐洲部署的應用程式為「e~」。
GAE_DEPLOYMENT_ID 目前部署的 ID。
GAE_ENV App Engine 環境。設為 standard
GAE_INSTANCE 服務目前正在執行的執行個體 ID。
GAE_MEMORY_MB 應用程式程序可用的記憶體量,以 MB 為單位。
GAE_RUNTIME app.yaml 檔案中指定的執行階段。
GAE_SERVICE app.yaml 檔案中指定的服務名稱。如果未指定服務名稱,則會設為 default
GAE_VERSION 服務目前的版本標籤。
GOOGLE_CLOUD_PROJECT 與應用程式相關聯的 Google Cloud 專案 ID。
PORT 接受 HTTP 要求的通訊埠。
NODE_ENV (僅適用於 Node.js 執行階段) 在部署服務時設定為 production

您可以在 app.yaml 檔案中定義其他環境變數,但無法覆寫上述值 (NODE_ENV 除外)。

HTTPS 和轉送 Proxy

App Engine 會在負載平衡器上終止 HTTPS 連線,並將要求轉送至您的應用程式。部分應用程式需要判斷原始要求 IP 和通訊協定。使用者的 IP 位址會顯示在標準 X-Forwarded-For 標頭中。需要這項資訊的應用程式應將其網路架構設定為「信任 Proxy」。

檔案系統存取權

執行階段包含可寫入的 /tmp 目錄,其他所有目錄都只有唯讀存取權。寫入 /tmp 會佔用系統記憶體。

中繼資料伺服器

應用程式的每個執行個體都可以使用 App Engine 中繼資料伺服器來查詢與執行個體和專案相關的資訊。

您可以透過以下端點存取中繼資料伺服器:

  • http://metadata
  • http://metadata.google.internal

傳送至中繼資料伺服器的要求必須包含要求標頭 Metadata-Flavor: Google。此標頭表示要求是為了擷取中繼資料值而傳送。

下表列出可讓您針對特定中繼資料發出 HTTP 要求的端點:

中繼資料端點 說明
/computeMetadata/v1/project/numeric-project-id 指派給專案的專案編號。
/computeMetadata/v1/project/project-id 指派給專案的專案 ID。
/computeMetadata/v1/instance/region 執行個體執行的區域。
/computeMetadata/v1/instance/service-accounts/default/aliases
/computeMetadata/v1/instance/service-accounts/default/email 指派給專案的預設服務帳戶電子郵件。
/computeMetadata/v1/instance/service-accounts/default/ 列出專案的所有預設服務帳戶。
/computeMetadata/v1/instance/service-accounts/default/scopes 列出預設服務帳戶的所有支援範圍。
/computeMetadata/v1/instance/service-accounts/default/token 傳回可用來向其他 Google Cloud API 驗證應用程式的驗證憑證。

舉例來說,如要擷取專案 ID,請將要求傳送至 http://metadata.google.internal/computeMetadata/v1/project/project-id