要求的處理方式

區域 ID

REGION_ID 是 Google 根據您在建立應用程式時選取的地區所指派的縮寫代碼。此代碼不對應至國家/地區或省份,即使部分區域 ID 可能與常用的國家/地區和省份代碼相似。如果是 2020 年 2 月後建立的應用程式,App Engine 網址會包含 REGION_ID.r。如果是這段時間前建立的現有應用程式,網址可選擇是否包含地區 ID。

進一步瞭解區域 ID

本文件說明 App Engine 應用程式如何接收要求及傳送回應。

詳情請參閱要求標頭和回應參考資料

如果您的應用程式使用服務,則可以設定要求的位址,將要求傳送到特定服務或該服務的特定版本。如要進一步瞭解服務的定址功能,請參閱要求的轉送方式一文。

處理要求

您的應用程式負責啟動網路伺服器和處理要求。 只要是適用於您開發語言的網路架構,您都可以使用。

App Engine 會執行應用程式的多個執行個體,每個執行個體都有自己專用的網路伺服器來處理要求。每個要求均有可能轉送至任何一個執行個體,因此來自同一個使用者的連續要求不一定會送到相同的執行個體。執行個體可以並行處理多個要求,執行個體的數量能夠隨流量自動調整。您也可以在 app.yaml 檔案中設定 max_concurrent_requests 元素,藉此變更執行個體可以處理的並行要求數量。

App Engine 的 Go 執行階段使用標準的 http 套件做為 Go 程式與 App Engine 伺服器之間的介面。當 App Engine 收到應用程式的網路要求時,就會叫用與該要求網址相關聯的 http.Handler

下列示例是一個完整的 Go 應用程式,會向使用者輸出採用硬式編碼的 HTML 字串:


// Sample helloworld is an App Engine app.
package main

import (
	"fmt"
	"log"
	"net/http"
	"os"
)



func main() {
	http.HandleFunc("/", indexHandler)

	port := os.Getenv("PORT")
	if port == "" {
		port = "8080"
		log.Printf("Defaulting to port %s", port)
	}

	log.Printf("Listening on port %s", port)
	if err := http.ListenAndServe(":"+port, nil); err != nil {
		log.Fatal(err)
	}
}



// indexHandler responds to requests with our greeting.
func indexHandler(w http.ResponseWriter, r *http.Request) {
	if r.URL.Path != "/" {
		http.NotFound(w, r)
		return
	}
	fmt.Fprint(w, "Hello, World!")
}

配額與限制

App Engine 會在流量增加時自動分配資源給您的應用程式,然而這項作業會受到下列限制:

  • 對於低延遲時間的應用程式 (回應要求的時間不到一秒),App Engine 會保留自動調整資源配置的容量。

  • 大幅受到 CPU 限制的應用程式可能也會產生一些額外的延遲時間,以便和相同伺服器上的其他應用程式有效率地共用資源。對靜態檔案的要求則不受這些延遲限制。

每個傳送至應用程式的要求均會計入「Requests」(要求) 限制。 而回應要求所傳送的資料則會計入「Outgoing Bandwidth (billable)」(連出頻寬 (可計費)) 限制。

HTTP 及 HTTPS (加密連線) 要求均會計入「Requests」(要求)、「Incoming Bandwidth (billable)」(連入頻寬 (可計費)) 及「Outgoing Bandwidth (billable)」(連出頻寬 (可計費)) 的限制。Google Cloud 控制台的「Quota Details」(配額詳細資料) 頁面也會個別回報「Secure Requests」(安全性要求)、「Secure Incoming Bandwidth」(安全連入頻寬) 和「Secure Outgoing Bandwidth」(安全連出頻寬) 的值,以供參考之用。僅有 HTTPS 要求會計入這些值。詳情請參閱配額頁面。

要求處理常式的使用配額還受到下列特別限制:

限制 大小
要求大小 32 MB
回應大小 32 MB
要求逾時 視應用程式使用的資源調度類型而定
檔案總數量的上限 (應用程式檔案和靜態檔案) 總計 10,000 個
每個目錄 1,000 個
應用程式檔案大小上限 32 MB
靜態檔案的大小上限 32 MB
所有應用程式和靜態檔案的總大小上限 前 1 GB 免費
前 1 GB 過後,每個月每 GB$ 0.026 美元
待處理要求逾時 10 秒
單一要求標頭欄位的大小上限 標準環境中的第二代執行階段為 8 KB。如果傳送至這些執行階段的要求標頭欄位超過 8 KB,系統會傳回 HTTP 400 錯誤。

要求限制

所有 HTTP/2 要求在轉送到應用程式伺服器時,都會轉譯成 HTTP/1.1 要求。

回應限制

  • 動態回應大小上限為 32 MB。如果指令碼處理常式產生大於此上限的回應,伺服器會傳回空白回應並顯示「500 Internal Server Error」(內部伺服器錯誤) 狀態碼。這項限制不適用於從舊版 Blobstore 和 Cloud Storage 提供資料的回應。

  • 第二代執行階段的回應標頭大小上限為 8 KB。 如果回應標頭超出這項限制,系統會傳回 HTTP 502 錯誤,且記錄檔會顯示 upstream sent too big header while reading response header from upstream

要求標頭

傳入 HTTP 要求包含用戶端傳送的 HTTP 標頭。基於安全性考量,部分標頭在送達應用程式之前會由中繼 Proxy 進行處理或修改。

詳情請參閱要求標頭參考資料

處理要求逾時

App Engine 已針對要求持續時間短暫的應用程式進行最佳化,尤其是回應要求只需耗費數百毫秒的應用程式。效率良好的應用程式能快速回應大部分的要求,至於回應速度不夠快的應用程式,則無法隨著 App Engine 的基礎架構妥善調度資源。為確保達到這個效能水準,系統會強制設定要求逾時上限,所有應用程式都必須在時限內回應。

如果應用程式超過這個期限,App Engine 會中斷要求處理常式。如果是 Go 要求處理常式,系統會停止處理作業,而執行階段環境會將「HTTP 500 Internal Server Error」(內部伺服器錯誤) 傳回用戶端。

回應

App Engine 會使用 RequestResponseWriter 呼叫處理常式,然後等候處理常式寫入 ResponseWriter 並回傳。當處理常式回傳時,ResponseWriter 內部緩衝區的資料就會傳送給使用者。

這個過程與編寫使用 http 套件的一般 Go 程式幾乎相同。

您產生的回覆會受到大小限制,而且在傳回用戶端前可能已經過修改。

詳情請參閱要求回應參考資料

串流回應

若資料在要求處理過程中,以增量區塊的形式傳送至用戶端,那麼 App Engine 並不支援此類資料的串流回應。系統會依上述方式收集所有來自程式碼的資料,並做為單一 HTTP 回應傳送。

回應壓縮

如果程式碼傳回的回應符合下列條件,App Engine 會壓縮回應中的資料:

  • 要求包含 Accept-Encoding 標頭,其中 gzip 是值。
  • 回應包含 HTML、CSS 或 JavaScript 等文字資料。

如果 App Engine 靜態檔案或目錄處理常式傳回的回應符合下列所有條件,系統就會壓縮回應資料:

  • 要求包含 Accept-Encoding,且 gzip 是其中一個值。
  • 用戶端能夠接收壓縮格式的回應資料。 Google 前端會維護一份用戶端清單,列出已知會發生壓縮回應問題的用戶端。即使要求標頭包含 Accept-Encoding: gzip,這些用戶端也不會收到應用程式中靜態處理常式的壓縮資料。
  • 回應包含 HTML、CSS 或 JavaScript 等文字資料。

注意事項:

  • 用戶端可以將 Accept-EncodingUser-Agent 要求標頭都設為 gzip,強制壓縮文字型內容類型。

  • 如果要求未在 Accept-Encoding 標頭中指定 gzip,App Engine 就不會壓縮回應資料。

  • Google 前端會快取 App Engine 靜態檔案和目錄處理常式的回應。視多項因素而定 (例如最先快取的回應資料類型、您在回應中指定的 Vary 標頭,以及要求中包含的標頭),用戶端可能會要求壓縮資料,但收到未壓縮的資料,反之亦然。詳情請參閱回應快取

回應快取

Google 前端,以及可能的使用者瀏覽器和其他中繼快取 Proxy 伺服器,會根據您在回應中指定的標準快取標頭,快取應用程式的回應。您可以透過架構、直接在程式碼中,或透過 App Engine 靜態檔案和目錄處理常式,指定這些回應標頭。

在 Google 前端,快取金鑰是要求的完整網址。

快取靜態內容

為確保用戶端在發布靜態內容後,能立即收到更新,建議您從版本目錄 (例如 css/v1/styles.css) 提供靜態內容。快取到期前,Google 前端不會驗證快取 (檢查更新內容)。即使快取過期,只要要求網址的內容未變更,快取就不會更新。

您可以在 app.yaml 中設定下列回應標頭,影響 Google 前端快取內容的方式和時間:

  • 應設為 public,Google 前端才能快取內容;除非您指定 Cache-Control privateno-store 指令,否則 Google 前端也可能會快取內容。Cache-Control如果您未在 app.yaml 中設定這個標頭,App Engine 會自動為靜態檔案或目錄處理常式處理的所有回應新增這個標頭。詳情請參閱「新增或取代的標頭」。

  • Vary:如要讓快取根據要求中傳送的標頭,針對網址傳回不同的回應,請在 Vary 回應標頭中設定一或多個下列值:AcceptAccept-EncodingOriginX-Origin

    由於其他 Vary 值可能具有高基數,因此系統不會快取這些值的資料。

    例如:

    1. 您指定下列回應標頭:

      Vary: Accept-Encoding

    2. 應用程式會收到含有 Accept-Encoding: gzip 標頭的要求。App Engine 會傳回壓縮回應,而 Google 前端會快取回應資料的 gzip 版本。後續所有包含 Accept-Encoding: gzip 標頭的這類網址要求,都會從快取收到經過 gzip 壓縮的資料,直到快取失效為止 (快取過期後內容變更)。

    3. 您的應用程式收到不含 Accept-Encoding 標頭的要求。App Engine 會傳回未壓縮的回應,而 Google Frontend 會快取未壓縮的回應資料版本。後續對這個網址的所有要求,只要不含 Accept-Encoding 標頭,都會從快取接收壓縮資料,直到快取失效為止。

    如未指定 Vary 回應標頭,Google 前端會為網址建立單一快取項目,並用於所有要求,不論要求中的標頭為何。例如:

    1. 您未指定 Vary: Accept-Encoding 回應標頭。
    2. 要求包含 Accept-Encoding: gzip 標頭,且回應資料的 gzip 壓縮版本會快取。
    3. 第二個要求不含 Accept-Encoding: gzip 標頭。 不過,由於快取包含回應資料的 gzip 壓縮版本,即使用戶端要求未壓縮的資料,回應仍會經過 gzip 壓縮。

要求中的標頭也會影響快取:

  • 如果要求包含 Authorization 標頭,Google 前端不會快取內容。

快取到期

根據預設,App Engine 靜態檔案和目錄處理常式新增至回應的快取標頭,會指示用戶端和 Google 前端等網路 Proxy 在 10 分鐘後使快取失效。

擁有指定到期時間的檔案在傳輸之後,通常就無法從網路 Proxy 快取中清除,就算使用者清除了自己的瀏覽器快取也沒辦法。重新部署新版應用程式時,並不會重設任何快取。因此,如果您打算修改靜態檔案,請為其設定較短的效期 (不超過一小時)。在大多數情況下,預設的 10 分鐘效期即為適當的設定。

如要變更所有靜態檔案和目錄處理常式的預設到期日,請在 app.yaml 檔案中指定 default_expiration 元素。如要為個別處理常式設定特定到期時間,請在 app.yaml 檔案的處理常式元素中指定 expiration 元素。

您在到期元素時間中指定的值,將用於設定 Cache-ControlExpires HTTP 回應標頭。

強制 HTTPS 連線

基於安全性考量,所有應用程式皆應鼓勵用戶端透過 https 連線。如要指示瀏覽器針對指定網頁或整個網域採用 https 而非 http,請在回應中設定 Strict-Transport-Security 標頭。例如:

Strict-Transport-Security: max-age=31536000; includeSubDomains
如要為應用程式提供的任何靜態內容設定這個標頭,請將標頭新增至應用程式的靜態檔案和目錄處理常式

如要為程式碼產生的回覆設定這個標頭,請使用 secureheader 套件

處理非同步背景工作

背景工作是指應用程式在傳送 HTTP 回應後,為要求執行的任何工作。請避免在應用程式中執行背景工作,並檢查程式碼,確認在您傳送回應之前,所有非同步作業皆已完成。

如果是長時間執行的工作,建議使用 Cloud Tasks。使用 Cloud Tasks 時,HTTP 要求會長時間存在,且只有在任何非同步工作結束後才會傳回回應。