在將應用程式的程式碼載入到新建立的執行個體時,您可以使用暖機要求來減少要求及回覆的延遲時間。
App Engine 經常需要將應用程式的程式碼載入至新的執行個體。載入執行個體作業可能會在發生以下情況時進行:
- 重新部署應用程式的版本時。
- 因要求的負載超過目前這組運作中執行個體的容量,而建立新的執行個體時。
- 基礎架構或實體硬體進行維護及修復時。
將應用程式的程式碼載入至新的執行個體時,可能會產生載入要求。載入要求可能會讓使用者面臨的要求延遲時間增加,但可使用「暖機要求」來避免此延遲時間增加情形。暖機要求會在任何即時要求到達該執行個體前,先將您應用程式的程式碼載入至新的執行個體。
如果您的應用程式啟用了暖機要求,App Engine 會嘗試偵測應用程式何時需要新的執行個體,並發出暖機要求來初始化新的執行個體。然而,嘗試偵測的功能並非在每種情況下均能有效運作。因此,即使應用程式已啟用暖機要求,仍可能會產生載入要求。舉例來說,如果您的應用程式沒有提供流量,則向應用程式發出的第一個要求一律為載入要求,而非暖機要求。
如同其他所有向 App Engine 應用程式發出的要求,暖機要求也會計入執行個體時數。在大多數啟用暖機要求的情況下,您不會發現執行個體小時數增加,因為應用程式只會在暖機要求中初始化,而非載入要求。如果您決定執行更多工作,例如在暖機要求期間進行預先快取,則執行個體小時用量可能會增加。如果您將 min_idle_instances
設為大於 0
,這些執行個體首次啟動時可能會出現暖機要求,但在該時間過後,這些執行個體仍可供使用。
啟用暖機要求
App Engine 排程器會使用暖機要求,並依據使用者提供的設定,控制執行個體的自動資源調度。在 App Engine Java 執行階段中,暖機要求預設為啟用,所以 App Engine 會向 /_ah/warmup
發出 GET
要求,讓您可以在必要時回應和初始化應用程式的程式碼。您可以使用下列任一方法來回應暖機要求:
- 使用
<load-on-startup>
Servlet - 提供暖機邏輯最簡單的方式,就是在
web.xml
設定檔中將您自己的 Servlet 標記為<load-on-startup>
。 - 使用
ServletContextListener
- 可讓您執行自訂邏輯,再透過暖機要求或載入要求來首次叫用任何 Servlet。
- 使用自訂暖機 Servlet
- 「僅」在暖機要求期間而非載入要求期間,使用自訂暖機 Servlet 叫用 Servlet 的
service
方法。
視您選用的方法而定,您可能需要為 /_ah/warmup
實作自己的處理常式。
事前準備
如果已將暖機要求啟用,則排程器會在判定需要更多執行個體時啟動執行個體。排程器會使用暖機要求啟動應用程式,因此即使您的應用程式不處理這些暖機要求,您還是會在記錄檔中看到這些要求。
以下訊息表示 /_ah/warmup
記錄中的暖機要求:
This request caused a new process to be started for your application, and thus caused your application code to be loaded for the first time. This request may thus take longer and use more CPU than a typical request for your application.
請注意,系統不保證會呼叫暖機要求,並且在某些狀況下會改為傳送載入要求,例如:該執行個體為首先啟動的執行個體,或是流量發生遽增。不過,如果暖機要求已啟用,系統會「盡量」嘗試將要求傳送至暖機完成的執行個體。
在 Java 8 中,暖機要求預設為啟用。如要啟用這些功能,請將 - warmup
新增至 appengine-web.xml
中的 inbound_services
指令。由於暖機預設為啟用,因此如果您之前部署的應用程式在 appengine-web.xml
中停用了暖機要求,只需要明確予以啟用即可。在這種情況下,您必須將 <warmup-requests-enabled>
值設為 true
,然後重新部署。
使用 <load-on-startup>
Servlet
提供暖機邏輯最簡單的方式,就是在 web.xml
中將您自己的 Servlet 標記為 <load-on-startup>
。這個方法不需要變更您的應用程式程式碼,並且會在您應用程式初始化時,初始化所有指定的 Servlet。
在 web.xml
檔案中,針對您要在啟動時載入的 Servlet,將 <load-on-startup>1</load-on-startup>
元素新增至 <servlet>
元素。例如:
<servlet>
<servlet-name>my-servlet</servlet-name>
<servlet-class>com.company.MyServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
這些程式碼會載入指定的 Servlet 類別,並叫用 Servlet 的 init()
方法。暖機要求會在處理任何即時要求之前,先初始化指定的 Servlet。但如果沒有任何暖機要求,則會在對新的執行個體發出第一個要求時,註冊 <load-on-startup>
中指定的 Servlet,導致產生載入要求。如先前所述,App Engine 可能不會在每次應用程式需要新的執行個體時,發出暖機要求。
使用 ServletContextListener
如要在叫用任何 Servlet 之前先執行您的自訂邏輯:
在
web.xml
檔案中註冊ServletContextListener
。<listener> <listener-class>com.company.MyListener</listener-class> </listener>
提供 Servlet 和篩選器程式碼,並一併提供類別:
public class MyListener implements ServletContextListener { public void contextInitialized(ServletContextEvent event) { // This will be invoked as part of a warmup request, or // the first user request if no warmup request was invoked. } public void contextDestroyed(ServletContextEvent event) { // App Engine does not currently invoke this method. } }
ServletContextListener
會在暖機要求期間執行。如果沒有任何暖機要求,則會在對新執行個體發出第一個要求時執行。這可能會產生載入要求。
使用自訂暖機 Servlet
自訂暖機 Servlet「僅」會在暖機要求期間叫用 Servlet 的 service
方法。在自訂暖機 Servlet 中加入成本較高的邏輯後,即可避免載入要求的載入時間增加。
如要建立自訂暖機 Servlet,只要在 web.xml
中覆寫 _ah_warmup
的內建 Servlet 定義即可:
<servlet>
<servlet-name>_ah_warmup</servlet-name>
<servlet-class>com.company.MyWarmupServlet</servlet-class>
</servlet>