toflar / psr6-symfony-http-cache-store
为Symfony的HttpCache反向代理提供的替代存储实现,支持自动删除过期条目和基于标签的缓存失效。
Requires
- php: ^8.0
- symfony/cache: ^6.0 || ^7.0
- symfony/http-foundation: ^6.0 || ^7.0
- symfony/http-kernel: ^6.0 || ^7.0
- symfony/lock: ^6.0 || ^7.0
- symfony/options-resolver: ^6.0 || ^7.0
Requires (Dev)
- symfony/phpunit-bridge: ^6.0 || ^7.0
README
支持的分支
- 对于PHP ^7.2和Symfony <6,使用版本3.x
- 对于PHP ^8.0和Symfony >6,使用版本4.x
简介
Symfony的HttpCache
存储实现相对较旧,是在还没有单独的锁定和缓存组件的时候开发的。此外,过期的缓存条目从未被删除,因此您的缓存目录将永远继续增长,直到您手动删除它。
在过程中,我需要支持基于标签的缓存失效,这要归功于Symfony Cache组件,实施起来相当简单。
因此,这个包提供了一个替代的StoreInterface
实现,...
- ...而不是再次实现锁定和缓存机制,而是使用经过良好测试的Symfony Cache和Lock组件,默认情况下都使用本地文件系统适配器。
- ...得益于Cache组件的
TagAwareAdapterInterface
,支持基于标签的缓存失效。 - ...得益于Cache组件的
PrunableInterface
,支持在文件系统上自动删除过期的条目,以尝试防止文件系统被淹没。 - ...允许您使用不同的PSR-6缓存适配器以及不同的锁适配器,而不是本地文件系统适配器。但是,请小心选择合适的适配器,请见下方的警告。
- ...支持
BinaryFileResponse
实例。
安装
$ composer require toflar/psr6-symfony-http-cache-store
配置
对于Symfony 4/Flex结构,您需要调整您的index.php
如下
<?php // public/index.php $kernel = new Kernel($env, $debug); $kernel = new HttpCache( $kernel, new Psr6Store(['cache_directory' => $kernel->getCacheDir()]), null, ['debug' => $debug] );
就是这样,这就是所有要做的事情。Psr6Store将自动创建最适合您本地文件系统的最佳缓存和锁定适配器。
如果您想更进一步,可以通过构造函数传入一个包含$options
的数组来配置Psr6Store
-
cache_directory:默认缓存适配器和锁工厂的缓存目录的路径。
需要此选项或同时需要
cache
和lock_factory
。类型:
字符串
-
cache:明确指定您想使用的缓存适配器。
注意,如果您想使用缓存标签,此缓存必须实现
Symfony\Component\Cache\Adapter\TagAwareAdapterInterface
。确保lock
和cache
具有相同的范围。请参阅下方的警告!类型:
Symfony\Component\Cache\Adapter\AdapterInterface
默认:FilesystemAdapter
实例,带有cache_directory
-
lock_factory:明确指定您想使用的锁工厂。确保锁和缓存具有相同的范围。请参阅下方的警告!
类型:
Symfony\Component\Lock\Factory
默认:如果支持,则为带有SemaphoreStore
的Factory
,否则为FlockStore
-
prune_threshold:配置写入操作的数量,直到存储将删除过期的缓存条目。传递
0
以禁用自动删除。类型:
整数
默认:500
-
cache_tags_header:用于检查标签的HTTP头名称。
类型:
字符串
默认:Cache-Tags
-
generate_content_digests:是否生成内容摘要。有关更多信息,请参阅“生成内容摘要”。
类型:
布尔值
默认:true
生成内容摘要
默认情况下,此缓存实现会生成内容摘要。这意味着响应元数据与响应内容存储在单独的地方。如果多个响应具有相同的内容,它只会在缓存中存储一次。比较以下说明以了解差异
生成内容摘要:
不生成内容摘要:
生成内容摘要优化了缓存,使其使用的存储空间更少。然而,在查找过程中,使用它们也带来了需要第二次往返缓存以获取内容摘要的代价。
是否要使用内容摘要取决于您的PSR-6缓存后端。如果查找速度快且存储空间有限(例如Redis),您可能想使用内容摘要。如果查找较慢且存储不是问题(例如文件系统),您可能想禁用它们。
您可以使用generate_content_digests
配置选项来控制这种行为。
缓存BinaryFileResponse
实例
此缓存实现允许缓存BinaryFileResponse
实例,但文件实际上并不会复制到缓存目录。它只会尝试获取原始文件,如果该文件不存在,则存储返回null
,导致HttpCache将其视为缓存未命中并正常继续。这对于需要防止应用程序启动并从HttpCache提供响应的场景(例如缓存/favicon.ico
请求)非常理想。
缓存标记
通过添加包含标签的响应头(以逗号分隔的值)来标记缓存条目。默认情况下,该头名为Cache-Tags
,可以在cache_tags_header
中重写。
要使标签失效,请调用方法Psr6Store::invalidateTags
或使用来自FOSHttpCache库的PurgeTagsListener
来处理标签失效请求。
修剪过期的缓存项
默认情况下,此存储在每次执行500
次缓存写入操作后从缓存中删除过期的条目。获取数据不会影响性能。您可以通过prune_threshold
配置设置更改自动修剪的频率。
您还可以通过在缓存上调用prune()
方法手动触发修剪。例如,您可以实现一个cron作业,在配置的间隔加载存储并修剪它,以防止由于修剪而减慢随机请求的速度,这些请求是缓存未命中,因为它们必须等待修剪。如果您已设置cron作业,您应通过将阈值设置为0
来禁用自动修剪。
警告
您可以配置除文件系统以外的其他缓存适配器或锁存储。只有当您确定自己在做什么时才这样做。在此请求中,Fabien拒绝了将PSR-6存储支持添加到Symfony的AppCache
,以下是其论据:
- 使用文件系统允许
opcache
使缓存非常有效; - 缓存包含一些PHP(例如,当使用ESI时)且存储PHP不在文件系统中意味着
eval()
来自Redis / Memcache /...的字符串; - HttpCache非常早地触发,并且无法访问容器或任何其他内容。它应该保持这种方式以保持高效。
虽然第一点和第三点取决于您所做和所需的内容,但请确保遵守第二点。如果您使用Redis或Memcache等网络启用缓存,请确保它们是共享的。如果使用Redis或Memcache,请确保它们是共享的。
致谢
我想感谢David在为我们为酷炫的FOSHttpCache库集成工作时提供的宝贵反馈。