adrhumphreys / impetuous
静态缓存简单化
Requires
- guzzlehttp/guzzle: ^6.5
- silverstripe/admin: ^1.0
- silverstripe/framework: ^4.0
Requires (Dev)
- phpunit/phpunit: ^5.7
- squizlabs/php_codesniffer: ^3.0
This package is auto-updated.
Last update: 2024-09-14 06:39:41 UTC
README
页面静态缓存简单化。这将缓存200个GET响应,默认存储在public/cache
中。它将在请求时缓存这些文件,因此您不需要任何麻烦的队列。默认情况下,缓存文件将保留1天,然后将被绕过。当绕过时,如果路由仍然返回200,则将重新缓存,并再次提供该缓存(以下文档说明了如何更改)。
它不涵盖什么?
- 您需要实现一个失效策略(对于CDN,以下文档说明)
- 您需要在
DataObjects
上实现onAfterWrite/onAfterPublish/onAfterUnpublish/onAfterDelete
来清除它们相关页面的缓存(这对于发布时的页面已经做到,对于其他项以下有说明) - 您需要防止缓存特定请求,例如营销标签中的
cid
(以下文档说明) - 您需要决定重新缓存策略(默认为页面发布后,并在一天后失效)
- 您需要决定您的缓存头(以下文档说明)
- 头信息,目前还没有计划
那么它涵盖了什么?
- 在请求生命周期中缓存请求(这意味着您不会缓存未访问的页面)
- 可用于通过CDN进行失效的钩子方法
- 提供缓存文件的函数
- 存储与数据库记录一起的缓存文件的函数
- 关于缓存响应的报告
- 过滤以防止缓存错误的响应
- 能够以编程方式预热缓存
- 在缓存一段时间后自动重新缓存页面(默认为1天)
但它是如何扩展的?
这是个好问题,这取决于扩展的定义。缓存服务扩展起来没有太多问题。重新缓存整个站点的能力是一个棘手的问题。如果大多数对网站的请求都是新的未缓存的页面,那么您需要实现一些预加热策略。如果大多数页面提供相同的内容,那么您应该没问题,但是您应该考虑实现可缓存查询参数的白名单。特别是如果使用营销标签。
要求
- SilverStripe ^4.0
- 渴望冒险
安装
composer require adrhumphreys/impetuous dev-master
编辑您的public/index.php
文件,在Composer的自动加载器启动之前添加以下内容
$requestHandler = require '../vendor/adrhumphreys/impetuous/includes/impetuous.php'; if (false !== $requestHandler('cache')) { die; } else { header('X-Cache-Miss: ' . date(DateTime::COOKIE)); }
默认情况下,文件缓存时间为1天,要更改此时间,请编辑即将到来的行,将其设置为缓存希望保留的秒数。例如,$requestHandler('cache', 60)
将设置缓存时间为60秒。
您需要确保中间件CacheResponse
作为堆栈中的最后一个中间件应用
环境变量值
IMPETUOUS_CACHE_DIR
:这是缓存存储的位置,默认为cache
,IMPETUOUS_RECORD
:确定我们是否将在数据库中记录缓存
防止缓存特定路由
您想通过将Cache
注入为子类并更新shouldCache
以返回不应缓存的路由的false
来实现。例如,如果您想永远不缓存查询参数,它将看起来像
<?php namespace App; use AdrHumphreys\Impetuous\Cache; class CustomCache extends Cache { protected static function shouldCache(HTTPRequest $request, HTTPResponse $response): bool { // Don't cache query params if (count($request->getVars()) > 0) { return false; } return parent::shouldCache($request, $response); } }
控制缓存头信息
这由开发者来决定。你需要权衡不同方法的利弊。一个例子是将 Cache-Control
标头设置为较大的最大存活时间,并依赖 CDN 无效化(以下将提到)。这看起来可能像这样
$requestHandler = require '../vendor/adrhumphreys/impetuous/includes/impetuous.php'; if (false !== $requestHandler('cache')) { header('Cache-Control: public, maxage=3600'); die; }
CND 无效化
您需要通过 Invalidator
注入并处理 invalidate
和 invaldidateAll
。当一个缓存条目被无效化时,invalidate
会传递条目的 URL,然后您可以在选择的 CDN 中使 URL 无效。
当链接项更改时重新缓存
这留给了开发者来实现,以下是一个基本示例,您可以在需要时遵循。
<?php namespace App; class MyObject extends DataObject { private static $has_one = ['LinkedPage' => SiteTree::class]; public function onAfterWrite() { parent::onAfterWrite(); Cache::clear($this->LinkedPage()->Link()); } public function onBeforeDelete() { parent::onBeforeDelete(); Cache::clear($this->LinkedPage()->Link()); } }
预热缓存
您可以在 Cache::warmURLs($urls)
中调用,其中 $urls
是一个 URL 数组。您可以手动设置一个任务来预热特定的 URL。
包含的任务
- 清除:用于清除特定的缓存记录,这可能在开发或测试期间非常有用。
- 预热:用于预热特定的 URL,同样适用于开发/测试。
- ClearExpiredRecords:这最好作为一个 cron 任务来运行,它删除由于过期而不再提供服务的记录。
包含的报告
- 缓存报告:这将显示缓存 URL 的列表,文件位置以及它们被缓存的时间
尝试提高性能
对于没有任何查询参数的 URL,您可以从 Apache/Nginx 的文件缓存中响应。以下是一些示例配置,您可以尝试使用。对于带有查询参数的请求,我们需要回退到 PHP 来解析查询参数为文件名。
这将处理查询参数,然后您可以编辑您的 .htaccess
或 .conf
以配置其他路由,如下所示:.htaccess
## CONFIG FOR STATIC PUBLISHING
# Cached content - sub-pages (site in the root of a domain)
RewriteCond %{REQUEST_METHOD} ^GET|HEAD$
RewriteCond %{QUERY_STRING} ^$
RewriteCond %{REQUEST_URI} /(.*[^/])/?$
RewriteCond %{DOCUMENT_ROOT}/cache/%1.html -f
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule .* /cache/%1.html [L]
# Cached content - homepage (site in root of a domain)
RewriteCond %{REQUEST_METHOD} ^GET|HEAD$
RewriteCond %{QUERY_STRING} ^$
RewriteCond %{REQUEST_URI} ^/?$
RewriteCond %{DOCUMENT_ROOT}/cache/index.html -f
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule .* /cache/index.html [L]
.conf
:
# Otherwise, see if the file exists and serve if so, pass through if not (but regexs below take precedence over this)
# This checks if the static cache has been built, and server that static html.
# Order is the php copy, then the html copy, an actual file somewhere and at last pass it down to the webserver
location / {
try_files /cache/$request_uri.php /cache/$request_uri.html $uri @passthrough;
open_file_cache max=1000 inactive=120s;
open_file_cache_valid 5;
expires 5;
}
# PHP request, always pass to apache
location ~* \.php$ {
error_page 404 = @passthrough;
return 404;
}
# This is the backend webserver that is defined in the main nginx.conf
location @passthrough {
proxy_pass http://backend;
expires off;
}
许可协议
是我做的吗?是你做的!除了嘲笑我的编程能力之外,你可以用它来做任何事情。