缓存失效
“计算机科学中只有两件难事:缓存失效和命名。” -- Phil Karlton
一旦 URL 被网关缓存缓存,缓存将不再向应用程序请求该内容。这使得缓存能够提供快速响应并减少应用程序的负载。但是,您可能会面临交付过时内容的风险。解决此困境的方法是使用较长的缓存生命周期,但在内容更改时主动通知网关缓存。反向代理通常提供接收此类通知的通道,通常通过特殊的 HTTP 请求。
警告
虽然缓存失效功能强大,但请尽可能避免使用。如果您未能使某些内容失效,则可能会在很长一段时间内提供过时的缓存。相反,请使用较短的缓存生命周期或验证模型,并调整您的控制器以执行高效的验证检查,如 HTTP 缓存验证 中所述。
此外,由于失效是每种类型的反向代理特有的主题,因此使用此概念会将您绑定到特定的反向代理,或者需要额外的努力来支持不同的代理。
然而,有时您需要显式失效时可以获得的额外性能。对于失效,您的应用程序需要检测内容何时更改,并告诉缓存从其缓存中删除包含该数据的 URL。
提示
如果您想使用缓存失效,请查看 FOSHttpCacheBundle。此 bundle 提供了服务来帮助处理各种缓存失效概念,并记录了一些常见缓存代理的配置。
如果一个内容对应一个 URL,则 PURGE
模型效果良好。您可以使用 HTTP 方法 PURGE
(使用单词“PURGE”是一种约定,从技术上讲,这可以是任何字符串)而不是 GET
向缓存代理发送请求,并使缓存代理检测到这一点,并从缓存中删除数据,而不是去应用程序获取响应。
以下是如何配置 Symfony 反向代理 以支持 PURGE
HTTP 方法。首先,创建一个缓存内核,该内核覆盖 invalidate() 方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
// src/CacheKernel.php
namespace App;
use Symfony\Bundle\FrameworkBundle\HttpCache\HttpCache;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
// ...
class CacheKernel extends HttpCache
{
protected function invalidate(Request $request, bool $catch = false): Response
{
if ('PURGE' !== $request->getMethod()) {
return parent::invalidate($request, $catch);
}
if ('127.0.0.1' !== $request->getClientIp()) {
return new Response(
'Invalid HTTP method',
Response::HTTP_BAD_REQUEST
);
}
$response = new Response();
if ($this->getStore()->purge($request->getUri())) {
$response->setStatusCode(Response::HTTP_OK, 'Purged');
} else {
$response->setStatusCode(Response::HTTP_NOT_FOUND, 'Not found');
}
return $response;
}
}
然后,将该类注册为 装饰 http_cache
的服务
1 2 3 4 5 6 7 8 9 10 11 12 13
// src/CacheKernel.php
namespace App;
// ...
use Symfony\Component\DependencyInjection\Attribute\AsDecorator;
use Symfony\Component\DependencyInjection\Attribute\Autoconfigure;
#[Autoconfigure(bind: ['$surrogate' => '@?esi'])]
#[AsDecorator(decorates: 'http_cache')]
class CacheKernel extends HttpCache
{
// ...
}
危险
您必须以某种方式保护 PURGE
HTTP 方法,以避免随机人员清除您的缓存数据。
Purge 指示缓存删除资源的所有变体(根据 Vary
标头,请参阅 HTTP 缓存的 Vary)。Purge 的替代方法是刷新内容。刷新意味着指示缓存代理丢弃其本地缓存并再次获取内容。这样,新内容已在缓存中可用。刷新的缺点是变体不会失效。
在许多应用程序中,相同的 content bit 用于具有不同 URL 的各种页面上。对于这些情况,存在更灵活的概念
- Banning 使与 URL 或其他条件上的正则表达式匹配的响应失效;
- 缓存标签 允许您为响应中使用的每个内容添加标签,以便您可以使包含特定内容的所有 URL 失效。