HTTP 快取
豐富的網路應用程式的本質意味著它們是動態的。無論您的應用程式多麼有效率,每個請求始終包含比服務靜態檔案更多的額外開銷。通常,這沒問題。但是,當您需要請求速度如閃電般快速時,您需要 HTTP 快取。
站在巨人的肩膀上進行快取
透過 HTTP 快取,您可以快取頁面的完整輸出(即回應),並在後續請求中完全繞過您的應用程式。快取完整回應對於高度動態的網站並非總是可行,還是可行?透過邊緣端包含 (ESI),您可以在您網站的僅片段上使用 HTTP 快取的功能。
Symfony 快取系統與眾不同,因為它依賴於 RFC 7234 - 快取 中定義的 HTTP 快取的簡潔性和強大功能。Symfony 沒有重新發明快取方法,而是擁抱定義網路上基本通訊的標準。一旦您了解基本的 HTTP 驗證和過期快取模型,您將準備好掌握 Symfony 快取系統。
由於使用 HTTP 快取並非 Symfony 獨有,因此已經存在許多關於該主題的文章。如果您是 HTTP 快取的新手,強烈建議 Ryan Tomayko 的文章 快取的作用。另一個深入的資源是 Mark Nottingham 的 快取教學。
使用閘道快取進行快取
當使用 HTTP 快取時,快取與您的應用程式完全分離,並位於您的應用程式和發出請求的用戶端之間。
快取的工作是接受來自用戶端的請求,並將它們傳回您的應用程式。快取也將接收來自您的應用程式的回應,並將它們轉發給用戶端。快取是用戶端和您的應用程式之間請求-回應通訊的「中間人」。
在此過程中,快取將儲存每個被視為「可快取」的回應(請參閱 HTTP 快取)。如果再次請求相同的資源,快取會將快取的回應傳送給用戶端,完全忽略您的應用程式。
這種快取類型稱為 HTTP 閘道快取,並且存在許多,例如 Varnish、反向代理模式下的 Squid 和 Symfony 反向代理。
提示
閘道快取有時稱為反向代理快取、代理快取,甚至 HTTP 加速器。
Symfony 反向代理
Symfony 隨附一個以 PHP 撰寫的反向代理(即閘道快取)。它不像 Varnish 那樣是功能完善的反向代理快取,但它是入門的好方法。
提示
有關設定 Varnish 的詳細資訊,請參閱 如何使用 Varnish 加速我的網站。
使用 framework.http_cache
選項為 prod 環境 啟用代理
1 2 3 4
# config/packages/framework.yaml
when@prod:
framework:
http_cache: true
核心將立即充當反向代理:快取來自您應用程式的回應並將其傳回給用戶端。
代理具有合理的預設組態,但可以透過 一組選項 進行微調。
在 偵錯模式 下,Symfony 會自動將 X-Symfony-Cache
標頭新增至回應。您也可以使用 trace_level
組態選項,並將其設定為 none
、short
或 full
以新增此資訊。
short
將僅新增主要請求的資訊。它以簡潔的方式撰寫,使其易於記錄在您的伺服器記錄檔中。例如,在 Apache 中,您可以在 LogFormat
格式語句中使用 %{X-Symfony-Cache}o
。此資訊可用於擷取有關您路由的快取效率的一般資訊。
提示
您可以使用 trace_header
組態選項變更用於追蹤資訊的標頭名稱。
讓您的回應可 HTTP 快取
一旦您新增了反向代理快取(例如 Symfony 反向代理或 Varnish),您就可以快取您的回應了。為此,您需要溝通到您的快取,哪些回應是可快取的以及快取多久。這是透過在回應上設定 HTTP 快取標頭來完成的。
HTTP 指定了四個回應快取標頭,您可以設定它們以啟用快取
Cache-Control
Expires
ETag
Last-Modified
這四個標頭用於透過兩種不同的模型來協助快取您的回應
過期快取
快取回應的最簡單方法是將其快取特定時間量
1 2 3 4 5 6 7 8 9
// src/Controller/BlogController.php
use Symfony\Component\HttpKernel\Attribute\Cache;
// ...
#[Cache(public: true, maxage: 3600, mustRevalidate: true)]
public function index(): Response
{
return $this->render('blog/index.html.twig', []);
}
由於此新程式碼,您的 HTTP 回應將具有以下標頭
1
Cache-Control: public, maxage=3600, must-revalidate
這會告知您的 HTTP 反向代理將此回應快取 3600 秒。如果任何人在 3600 秒之前再次請求此 URL,則根本不會點擊您的應用程式。如果您使用的是 Symfony 反向代理,請查看 X-Symfony-Cache
標頭,以取得有關快取命中和未命中的偵錯資訊。
提示
請求的 URI 用作快取金鑰(除非您變更)。
這提供了出色的效能,並且易於使用。但是,不支援快取失效。如果您的內容變更,您需要等到快取過期頁面才會更新。
提示
實際上,您可以手動使您的快取失效,但它不是 HTTP 快取規格的一部分。請參閱 快取失效。
如果您需要為許多不同的控制器動作設定快取標頭,請查看 FOSHttpCacheBundle。它提供了一種根據 URL 模式和其他請求屬性定義快取標頭的方法。
最後,有關過期快取的更多資訊,請參閱 HTTP 快取過期。
驗證快取
透過過期快取,您說「快取 3600 秒!」。但是,當有人更新快取內容時,在快取過期之前,您不會在您的網站上看到該內容。
如果您需要立即看到更新的內容,您需要使您的快取失效或使用驗證快取模型。
有關詳細資訊,請參閱 HTTP 快取驗證。
安全方法:僅快取 GET 或 HEAD 請求
HTTP 快取僅適用於「安全」HTTP 方法(例如 GET 和 HEAD)。這表示三件事
- 不要嘗試快取 PUT 或 DELETE 請求。它不會運作,而且有充分的理由。這些方法旨在在變更應用程式狀態時使用(例如刪除部落格文章)。快取它們會阻止某些請求點擊和變更您的應用程式。
- POST 請求通常被認為是不可快取的,但是當它們包含明確的新鮮度資訊時,它們可以被快取。但是,POST 快取並未廣泛實作,因此如果可能,您應該避免使用它。
- 當回應 GET 或 HEAD 請求時,您絕不應該變更應用程式的狀態(例如更新部落格文章)。如果這些請求被快取,則未來的請求可能實際上不會點擊您的伺服器。
更多回應方法
Response 類別提供了許多與快取相關的更多方法。以下是最有用的方法
1 2 3 4 5
// marks the Response stale
$response->expire();
// forces the response to return a proper 304 response with no content
$response->setNotModified();
此外,大多數與快取相關的 HTTP 標頭都可以透過單個 setCache() 方法設定
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
// use this method to set several cache settings in one call
// (this example lists all the available cache settings)
$response->setCache([
'must_revalidate' => false,
'no_cache' => false,
'no_store' => false,
'no_transform' => false,
'public' => true,
'private' => false,
'proxy_revalidate' => false,
'max_age' => 600,
's_maxage' => 600,
'immutable' => true,
'last_modified' => new \DateTime(),
'etag' => 'abcdef'
]);
提示
當使用 #[Cache]
屬性時,所有這些選項也都可用。
HTTP 快取和使用者工作階段
每當在請求期間啟動工作階段時,Symfony 都會將回應轉換為私有的不可快取回應。這是最佳的預設行為,以防止快取私有使用者資訊(例如購物車、使用者個人資料詳細資訊等),並將其暴露給其他訪客。
但是,即使是使用工作階段的請求,在某些情況下也可以快取。例如,與某些使用者群組相關的資訊可以為屬於該群組的所有使用者快取。處理這些進階快取情境超出了 Symfony 的範圍,但可以使用 FOSHttpCacheBundle 來解決。
為了停用 Symfony 預設行為(使使用工作階段的請求不可快取),請將以下內部標頭新增至您的回應,Symfony 將不會修改它
1 2 3
use Symfony\Component\HttpKernel\EventListener\AbstractSessionListener;
$response->headers->set(AbstractSessionListener::NO_AUTO_CACHE_CONTROL_HEADER, 'true');
總結
Symfony 的設計旨在遵循經過驗證的規則:HTTP。快取也不例外。掌握 Symfony 快取系統意味著熟悉 HTTP 快取模型並有效地使用它們。這表示,除了僅依賴 Symfony 文件和程式碼範例之外,您還可以存取與 HTTP 快取和閘道快取(例如 Varnish)相關的大量知識。