Java Runtime Environment

透過 App Engine,您可以建構使用 Google 可擴充基礎架構與服務的網路應用程式。App Engine 會使用 Java 8 JVM 執行網路應用程式。App Engine 會叫用應用程式的 Servlet 類別,在這個環境中處理要求並準備回應。

App Engine 平台提供許多內建 API 服務,您的程式碼可以呼叫這些服務。您的應用程式也可以設定會按指定間隔執行的排程工作

為應用程式指定 Java 8 執行階段

如要讓您的應用程式使用 Java 8 執行階段,請將以下這一行新增至 appengine-web.xml 檔案:

<runtime>java8</runtime>

appengine-api.jar 檔案是 platform/google_appengine/google/appengine/tools/java/lib/impl/appengine-api.jar 下 Google Cloud CLI 隨附的檔案,代表 Java 適用的 App Engine API。您也可以使用 Maven 存放區存取此檔案,該存放區會列出所有版本。

您可以將這個 JAR 包含在應用程式的 WEB-INF/lib/ 目錄中,來選取應用程式使用的 API 版本,或者使用 Maven 來處理依附元件。如果新推出的 Java Runtime Environment 版本出現與現有應用程式不相容的變更,該環境將會使用新的主要版本號碼。

使用 Maven 來處理依附元件

您可以使用 Maven 管理所有依附元件。例如,這個 pom.xml 項目中包含 Maven Central 的最新 App Engine API (Rappengine-api-1.0-sdk):

<dependency>
    <groupId>com.google.appengine</groupId>
    <artifactId>appengine-api-1.0-sdk</artifactId>
    <version></version>
</dependency>

沙箱

App Engine Java 執行階段會針對跨多個網路伺服器的應用程式發布要求,並防止應用程式之間相互干擾。App Engine 應用程式不可以緩慢回應。應用程式收到的網路要求必須在要求逾時限制內處理完畢。處理序如果超出此回應限制,就會終止,以免導致網路伺服器負荷過重。

請注意,使用者唯一能夠寫入檔案的位置是 /tmp 目錄。/tmp 中的檔案將會耗用分配給執行個體的記憶體。儲存在這個位置的檔案僅對此執行個體可用,且僅適用於此特定執行個體的生命週期。

要讓您的應用程式取得資源檔案,常見的方法就是將您依賴的檔案封裝到應用程式的 WEB-INF 之下,然後使用 Class.getResource()ServletContext.getResource() 或類似方法從應用程式載入這些檔案。根據預設,WAR 中的所有檔案都是「資源檔案」。您可以使用 appengine-web.xml 檔案將這些資源檔案排除在這組檔案之外。

類別載入器 JAR 排序

有時候可能需要重新定義掃描 JAR 檔案的類別順序,藉以解決類別名稱之間的衝突。在這些情況下,您可以在 appengine-web.xml 檔案中新增包含 <priority-specifier> 元素的 <class-loader-config> 元素,賦予特定 JAR 檔案優先載入順序。例如:

<class-loader-config>
  <priority-specifier filename="mailapi.jar"/>
</class-loader-config>

這樣會使「mailapi.jar」成為除了 war/WEB-INF/classes/ 目錄中的 JAR 檔案以外,第一個搜尋的 JAR 檔案類別。

如果將多個 JAR 檔案設定為優先,則會使用這些檔案的原始載入順序 (彼此的相對順序)。換句話說,<priority-specifier> 元素本身的順序無關緊要。

討論串

有了 Java 8 執行階段,您就可以使用 App Engine 的 ThreadManager API 與 Java 的內建 API (例如 new Thread()) 建立執行緒。目前,如果您要呼叫 App Engine API (com.google.appengine.api.*),必須透過要求執行緒或使用 ThreadManager API 建立的執行緒呼叫這些 API。

應用程式可以執行以下動作:

如果您使用 currentRequestThreadFactory() 建立 ThreadPoolExecutor,則必須在 Servlet 要求完成之前明確呼叫 shutdown(),否則將會導致要求未完成,且應用程式伺服器最終也會失敗。請注意,某些程式庫可能會為您建立 ThreadPoolExecutors。

應用程式可對目前執行緒執行作業,例如 thread.interrupt()

每個要求都受限於 50 個並行 App Engine API 要求執行緒之內。

使用執行緒時,請使用高階並行物件,例如 ExecutorRunnable。這些物件會處理並行方面的許多細微但重要的細節,例如中斷排程和簿記

App Engine API 可為每個執行個體建立的並行背景執行緒數量上限為 10 個。這項限制不適用於與 App Engine API 無關的一般 Java 執行緒。

工具

支援的 IDE

Cloud Tools for IntelliJ 可讓您在 IntelliJ IDEA 中執行 App Engine 應用程式及偵錯。無須離開 IDE,就可以即時將 App Engine 專案部署至實際工作環境。

支援的建構工具

如要加快開發流程,您可以使用 Maven 或 Gradle 適用的 App Engine 快掛程式:

本機開發伺服器

開發伺服器會在本機電腦上執行您的應用程式,以進行開發與測試。伺服器會模擬 Datastore 服務。開發伺服器也會根據應用程式在測試期間執行的查詢,產生 Datastore 索引的設定。

並行與延遲

應用程式的延遲對提供流量所需的執行個體數量影響最大。若快速處理要求,一個執行個體就能處理許多要求。

單執行緒執行個體可以處理一個並行要求。因此,延遲與執行個體每秒能夠處理的要求數量之間具有直接關係。例如,延遲 10 毫秒相當於每個執行個體每秒處理 100 個要求。

多執行緒執行個體可以處理許多並行要求。因此,耗用的 CPU 和每秒要求數量之間具有直接關係。

Java 應用程式支援並行要求,因此,單一執行個體可以一邊處理新要求一邊等待其他要求完成。並行能大幅減少應用程式所需的執行個體數量,但您需要設計支援多工執行緒功能的應用程式。

例如,若一個 B4 執行個體 (約 2.4GHz) 處理一個要求需耗用 10 個 Mcycle,那麼您的每個執行個體每秒可以處理 240 個要求。若處理每個要求需耗用 100 個 Mcycle,則您的每個執行個體每秒可以處理 24 個要求。這些數字是理想情形,不過針對可在一個執行個體上完成的工作而言,算是相當實際。

App Engine Java 版本

所有版本號碼開頭為 2.x.x 的已發布構件都會使用開放原始碼發布機制。版本號碼為 1.9.9xx 或更早版本的已發布構件會使用內部建構系統。詳情請參閱 GitHub 存放區

環境變數

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

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

您可以app.yaml 檔案中定義其他環境變數,但無法覆寫上述的值。