透過 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。
應用程式可以執行以下動作:
- 實作
java.lang.Runnable
。 - 呼叫
com.google.appengine.api.ThreadManager.currentRequestThreadFactory()
即可建立執行緒工廠。 - 呼叫工廠的
newRequestThread
方法,傳入Runnable
、newRequestThread(runnable)
,或使用com.google.appengine.api.ThreadManager.currentRequestThreadFactory()
透過ExecutorService
傳回的工廠物件 (例如呼叫Executors.newCachedThreadPool(factory)
)。
如果您使用 currentRequestThreadFactory()
建立 ThreadPoolExecutor
,則必須在 Servlet 要求完成之前明確呼叫 shutdown()
,否則將會導致要求未完成,且應用程式伺服器最終也會失敗。請注意,某些程式庫可能會為您建立 ThreadPoolExecutors。
應用程式可對目前執行緒執行作業,例如 thread.interrupt()
。
每個要求都受限於 50 個並行 App Engine API 要求執行緒之內。
使用執行緒時,請使用高階並行物件,例如 Executor
和 Runnable
。這些物件會處理並行方面的許多細微但重要的細節,例如中斷與排程和簿記。
工具
支援的 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
檔案中定義其他環境變數,但無法覆寫上述的值。