Google Code 提供下列語言介面: English - Español - 日本語 - 한국어 - Português - Pусский - 中文(简体) - 中文(繁體)
「應用服務引擎」會在安全的「沙箱」環境中,使用 Java 6 JVM 執行您的 Java 網路應用程式。「應用服務引擎」會叫用應用程式的 servlet 類別,在這個環境中處理要求與準備回應。
在您使用 Java SDK 的 AppCfg 工具上傳應用程式時,「應用服務引擎」會為您的應用程式提供 Java 執行階段環境。
截至筆者撰稿時,「應用服務引擎 Java API」僅提供一個版本。這個 API 是由 SDK 的 appengine-api-*.jar 代表之 (其中 * 代表 API 和 SDK 的版本)。您可以將 JAR 納入 WEB-INF/lib/ 目錄,藉此選取應用程式要使用的 API 版本。如果 Java 執行階段環境推出新的版本,卻新增了無法與現有應用程式相容的變更,則該環境將擁有新的版本號碼。您的應用程式將繼續使用之前的版本,直到您使用新的版本 (來自較新的 SDK) 取代 JAR,並重新上傳應用程式為止。
收到應用程式的網頁要求時,「應用服務引擎」會叫用與 URL 相應的 servlet,如應用程式部署描述元 (WEB-INF/ 目錄的 web.xml 檔案) 所述。它會使用 Java Servlet API,為 servlet 提供要求資料,以及接收回應資料。
「應用服務引擎」使用多個網頁伺服器來執行您的應用程式,並可靠地自動調整用來處理要求的伺服器數量。指定的要求可能會透過傳送到任一部伺服器,而且處理它的伺服器,與來自相同使用者之前送出要求的處理伺服器,可能不是同一部。
下列 servlet 類別範例會在使用者的瀏覽器中顯示簡單的訊息。
import java.io.IOException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class MyServlet extends HttpServlet {
public void doGet(HttpServletRequest req, HttpServletResponse resp)
throws IOException {
resp.setContentType("text/plain");
resp.getWriter().println("Hello, world");
}
}
「應用服務引擎」會呼叫擁有要求物件和回應物件的 servlet,然後等待 servlet 填入回應物件並傳回。Servlet 傳回時,回應物件上的資料會傳送給使用者。
「應用服務引擎」不支援先傳送資料給用戶端,然後在應用程式中執行更多計算,再傳送更多資料。換言之,「應用服務引擎」不支援在回應單一要求時「串流」資料。
如果用戶端傳送 HTTP 標頭的要求指出用戶端可接受壓縮的 (gzip'd) 內容,則「應用服務引擎」會自動壓縮回應資料,並附加適當的回應標頭。它會使用 Accept-Encoding 和 User-Agent 的要求標頭來判斷用戶端是否能夠可靠地接收壓縮的回應。自訂用戶端可以強制壓縮內容,只要將 Accept-Encoding 和 User-Agent 標頭指定為「gzip」值即可。
要求處理常式必須在限制時間內 (一般是在 30 秒左右),根據要求產生並傳回回應。一旦超過限制時間,要求處理常式將遭到中斷。
Java 執行階段環境會擲回 com.google.apphosting.api.DeadlineExceededException,以中斷 servlet。如果要求處理常式未能捕捉此例外狀況,則與所有未捕捉到的例外狀況一樣,執行階段環境將傳回 HTTP 500 伺服器錯誤給用戶端。
要求處理常式可以捕捉此錯誤,並自訂回應。執行階段環境會在引發例外狀況後,給予要求處理常式較多時間 (一秒以內) 準備自訂回應。
回應一個要求的時間可能長達 30 秒,不過如果應用程式的要求都是短期要求,尤其是只需花費幾百毫秒的要求,則「應用服務引擎」將能展現最佳效能。有效率的應用程式可以快速回應絕大多數的要求。無法快速回應的應用程式,將無法順利地透過「應用服務引擎」的基礎結構擴充。
為了讓「應用服務引擎」將應用程式的要求分散到多個網頁伺服器,並防止應用程式彼此干擾,應用程式會在限制的「沙箱」環境中執行。在此環境中,應用程式可以執行程式碼、儲存和查詢「應用服務引擎」資料存放區的資料、使用「應用服務引擎」郵件、URL 擷取和使用者服務以及檢查使用者的網路要求和準備回應。
「應用服務引擎」無法執行下列動作:
Java 應用程式無法建立新的 java.lang.ThreadGroup 或新的 java.lang.Thread。這些限制也可以套用至使用執行緒的 JRE 類別。例如,應用程式無法建立新的 java.util.concurrent.ThreadPoolExecutor 或 java.util.Timer。應用程式「可以」對目前執行緒執行作業,例如 Thread.currentThread().dumpStack()。
Java 應用程式無法使用任何用於寫入檔案系統的類別,例如 java.io.FileWriter。應用程式可以使用諸如 java.io.FileReader 的類別,從檔案系統讀取自己的檔案。應用程式也可以將自己的檔案當做「資源」存取,例如使用 Class.getResource() 或 ServletContext.getResource()。
只有被歸類為「資源檔案」的檔案才能提供應用程式透過檔案系統存取。按照預設,WAR 的所有檔案均為「資源檔案」。您可以使用 appengine-web.xml 檔案排除 WAR 的檔案。
所有不適用於「應用服務引擎」的 java.lang.System 類別功能會遭到停用。
下列的 System 方法在「應用服務引擎」中沒有作用:exit()、gc()、runFinalization()、runFinalizersOnExit()
下列的 System 方法會傳回 null:inheritedChannel()、console()
應用程式無法提供或直接叫用任何原生的 JNI 程式碼。下列的 System 方法會引發 java.lang.SecurityException:load()、loadLibrary()、setSecurityManager()
應用程式可以完全、無限制地反映存取自己的檔案。它可以查詢任何私有成員 (使用 java.lang.reflect.AccessibleObject.setAccessible()),以及讀取或設定私有成員。
應用程式也可以反映在 JRE 和 API 類別上,例如 java.lang.String 和 javax.servlet.http.HttpServletRequest。不過,它只能存取這些類別的公開成員,無法存取受保護或私有成員。
應用程式無法反映任何不屬於它的類別,也無法透過 setAccessible() 方法規避這些限制。
「應用服務引擎」完全支援自訂類別載入。 不過請注意,「應用服務引擎」會覆寫所有 ClassLoader,以指派相同權限給應用程式所載入的所有類別。如果您要執行自訂類別載入,載入不信任的第三方程式碼時請特別留意。
存取 Java 標準程式庫 (Java 執行階段環境,或 JRE) 的類別時,僅限存取「應用服務引擎 JRE 白名單」所列出的類別。
您的應用程式可以使用 java.util.logging.Logger,將資訊寫入應用程式記錄。應用程式的記錄資料可以透過「管理控制台」檢視與分析,也可以透過 appcfg.sh request_logs 下載。「管理控制台」可以辨識 Logger 類別的記錄等級,並透過互動方式顯示不同等級的訊息。
「應用服務引擎」會擷取 servlet 寫入標準輸出串流 (System.out) 和標準錯誤串流 (System.err) 的所有資料,並記錄在應用程式記錄中。寫入標準輸出串流的資料會列為「INFO」等級記錄,而寫入標準錯誤串流的資料則會列為「WARNING」等級記錄。所有能夠記錄輸出或錯誤串流的記錄架構 (例如 log4j) 均可運作。不過,如需更精確地控制「管理控制台」的記錄等級,記錄架構必須使用 java.util.logging 介面卡。
import java.util.logging.Logger;
// ...
public class MyServlet extends HttpServlet {
private static final Logger log = Logger.getLogger(MyServlet.class.getName());
public void doGet(HttpServletRequest req, HttpServletResponse resp)
throws IOException {
log.info("An informational message.");
log.warning("A warning message.");
log.severe("An error message.");
}
}
「應用服務引擎 Java SDK」的 appengine-java-sdk/config/user/目錄包括 logging.properties 範本檔。如要使用這個範本,請將檔案複製到您的 WEB-INF/classes 目錄 (或 WAR 中的其他位置),然後將系統屬性 java.util.logging.config.file 複製到 "WEB-INF/classes/logging.properties" (或應用程式根目錄下的自選路徑)。您可以在 appengine-web.xml 檔案中設定系統屬性,如下所示:
<appengine-web-app xmlns="http://appengine.google.com/ns/1.0">
...
<system-properties>
<property name="java.util.logging.config.file" value="WEB-INF/classes/logging.properties" />
</system-properties>
</appengine-web-app>
「Eclipse 專用的 Google 外掛程式」新建專案精靈會建立這些記錄設定檔,並自動將它們複製到 WEB-INF/classes/。如果是 java.util.logging,您必須設定系統屬性才能使用這個檔案。
所有的系統屬性和環境變數都專屬於您的應用程式。設定系統屬性只會影響應用程式的屬性檢視畫面,不會影響 JVM 的檢視畫面。
您可以在部署描述元中設定應用程式的系統屬性和環境變數。
當「應用服務引擎」在應用程式伺服器初始化 JVM 時,它會設定下列系統屬性:
file.separatorpath.separatorline.separatorjava.versionjava.vendorjava.vendor.urljava.class.versionjava.specification.versionjava.specification.vendorjava.specification.namejava.vm.vendorjava.vm.namejava.vm.specification.versionjava.vm.specification.vendorjava.vm.specification.nameuser.dir應用程式的每個連入要求會算入「要求」的配額中。
接收要求而收到的資料會算入「連入頻寬 (可計費)」的配額中。回應要求而傳送的資料會算入「連出頻寬 (可計費)」的配額中。
HTTP 和 HTTPS (安全) 要求會算入「要求」、「連入頻寬 (可計費)」以及「連出頻寬 (可計費)」的配額中。「管理控制台」的 [Quota Details] (配額詳細資訊) 頁面也會另外提供「安全要求」、「安全連入頻寬」以及「安全連出頻寬」的數據,以供參考。只有 HTTPS 要求才會算入這些數據。
執行要求處理常式所花費的 CPU 處理時間會算入「CPU 時間 (可計費)」的配額中。
如需瞭解配額的詳細資訊,請參閱「配額」,或參閱「管理控制台」的「配額詳細資訊」一節。
除了配額之外,使用要求處理常式時也需遵循下列限制:
| 限制 | 大小 |
|---|---|
| 要求大小 | 10 MB |
| 回應大小 | 10 MB |
| 要求持續時間 | 30 秒 |
| 同時動態要求 | 30 |
| 應用程式檔案數量上限 | 1,000 |
| 靜態檔案數量上限 | 1,000 |
| 應用程式檔案大小上限 | 10 MB |
| 靜態檔案大小上限 | 10 MB |
| 所有應用程式和靜態檔案的總計大小上限 | 150 MB |
* 應用程式可以同時處理大約 30 個作用中的動態要求。這表示如果一個應用程式處理伺服器端要求的平均時間為 75 毫秒,則在沒有發生任何額外延遲的狀況下,每一秒最多可以處理 400 個要求 (1000 毫秒/秒 / 75 毫秒/要求 * 30 = 400)。為挪出空間給其他共用相同伺服器的應用程式,受到 CPU 嚴重限制的應用程式在處理長期執行的要求時,可能會發生額外的延遲。靜態檔案的要求則不會受到此限制的影響。