adrhumphreys/impetuous

静态缓存简单化

安装: 2

依赖项: 0

建议者: 0

安全: 0

星级: 0

关注者: 2

分支: 0

开放问题: 0

类型:silverstripe-vendormodule

dev-master 2020-08-13 21:40 UTC

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:这是缓存存储的位置,默认为cacheIMPETUOUS_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 注入并处理 invalidateinvaldidateAll。当一个缓存条目被无效化时,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;
}

许可协议

是我做的吗?是你做的!除了嘲笑我的编程能力之外,你可以用它来做任何事情。