設定暖機要求以改善效能

在將應用程式的程式碼載入到新建立的執行個體時,您可以使用暖機要求來減少要求及回應的延遲時間。

App Engine 經常需要將應用程式的程式碼載入至新的執行個體。發生以下情況時,可能會載入執行個體:

  • 重新部署應用程式的版本時。
  • 因要求產生的負載超過目前運作中執行個體的容量,而建立新的執行個體時。
  • 基礎架構或實體硬體進行維護及修復時。

將應用程式的程式碼載入至新的執行個體時,可能會產生載入要求。載入要求可能會增加使用者的要求延遲時間,但是使用「暖機要求」可避免延遲增加。暖機要求會在任何即時要求到達該執行個體前,先將您應用程式的程式碼載入至新的執行個體。

如果您的應用程式啟用了暖機要求,App Engine 會嘗試偵測應用程式何時需要新的執行個體,並發出暖機要求來初始化新的執行個體。然而,嘗試偵測的功能並非在每種情況下均能有效運作。因此,即使應用程式已啟用暖機要求,仍可能會產生載入要求。舉例來說,如果您的應用程式沒有提供流量,則向應用程式發出的第一個要求一律為載入要求,而非暖機要求。

如同其他所有向 App Engine 應用程式發出的要求,暖機要求也會計入執行個體時數。在大部分暖機要求已啟用的狀況下,您不會注意到執行個體時數增加,這是因為應用程式只是單純在暖機要求中 (而非載入要求) 進行初始化。如果您決定要執行更多工作,例如在暖機要求期間預先進行快取,則執行個體的時數使用量可能會增加。如果您有設定閒置執行個體的數量下限,則可能會在這些執行個體初次啟動時發生暖機要求,但這些執行個體從此之後就會保持可用的狀態。

啟用暖機要求

App Engine 排程器會使用暖機要求,並依據使用者提供的設定,控制執行個體的自動調整資源配置。App Engine 會在啟用暖機要求的情況下向 /_ah/warmup 發出 GET 要求。您可以針對這個要求實作處理常式,以執行應用程式專屬的工作,例如預先快取應用程式資料。

排程器判定需要更多執行個體時,就會啟動執行個體。由於排程器會使用暖機要求啟動執行個體,因此即使停用了暖機要求,這些要求仍可能會出現在記錄中。

提醒您,暖機要求並不保證能夠呼叫成功,並且在某些狀況下會改為傳送載入要求,例如:該執行個體為首先啟動的執行個體,或是流量發生遽增。不過,在暖機要求已啟用的情況下,系統會「儘可能」嘗試將要求傳送至已完成暖機作業的執行個體。

如要啟用暖機要求,請在 app.yaml 檔案中的 inbound_services 指令下方加入 warmup 元素。範例如下:

inbound_services:
- warmup

登錄處理常式

您可以在專案的 app.yaml 檔案中登錄處理暖機要求的指令碼。例如:

inbound_services:
- warmup

handlers:
- url: /_ah/warmup
  script: _go_app
  login: admin

這個範例會註冊處理常式,以監聽透過 app.go 檔案的指令碼處理常式向 /_ah/warmup 要求路徑發出的暖機要求。

建立處理常式

建立可處理傳送至 /_ah/warmup 的要求的處理常式。處理常式必須能夠執行應用程式所需的任何暖機邏輯。下列範例採用先前的範例做為基礎:


// Sample warmup demonstrates usage of the /_ah/warmup handler.
package main

import (
	"context"
	"fmt"
	"log"
	"net/http"
	"os"
	"time"

	"cloud.google.com/go/storage"
)

var startupTime time.Time
var client *storage.Client

func main() {
	// Perform required setup steps for the application to function.
	// This assumes any returned error requires a new instance to be created.
	if err := setup(context.Background()); err != nil {
		log.Fatalf("setup: %v", err)
	}

	// Log when an appengine warmup request is used to create the new instance.
	// Warmup steps are taken in setup for consistency with "cold start" instances.
	http.HandleFunc("/_ah/warmup", func(w http.ResponseWriter, r *http.Request) {
		log.Println("warmup done")
	})
	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)
	log.Fatal(http.ListenAndServe(fmt.Sprintf(":%s", port), nil))
}

// setup executes per-instance one-time warmup and initialization actions.
func setup(ctx context.Context) error {
	// Store the startup time of the server.
	startupTime = time.Now()

	// Initialize a Google Cloud Storage client.
	var err error
	if client, err = storage.NewClient(ctx); err != nil {
		return err
	}

	return nil
}

// indexHandler responds to requests with our greeting.
func indexHandler(w http.ResponseWriter, r *http.Request) {
	if r.URL.Path != "/" {
		http.NotFound(w, r)
		return
	}
	uptime := time.Since(startupTime).Seconds()
	fmt.Fprintf(w, "Hello, World! Uptime: %.2fs\n", uptime)
}

後續步驟

您可能會希望將資料值儲存於 Memcache 等記憶體內資料儲存庫,讓您的應用程式透過較少查詢迅速存取資料。

舉例來說,假設您想要建立並儲存自有網站的當前熱門文章清單,可以在暖機空間中建立清單,再將清單儲存至 Memcache。使用者要求傳入時,App Engine 無須執行任何資料儲存庫查詢作業,應用程式也能更快速地處理使用者要求。

本頁內容對您是否有任何幫助?請提供意見:

傳送您對下列選項的寶貴意見...

這個網頁
Go 適用的 App Engine 標準環境