webiny/hrc

基于进入的HTTP请求的缓存规则进行缓存的缓存管理层。

v1.0.0 2017-09-29 07:32 UTC

This package is not auto-updated.

Last update: 2024-09-14 17:26:40 UTC


README

这是一个提供围绕您的缓存的控制机制的缓存管理系统。缓存与进入的HTTP请求相关联。实际上,这意味着您可以根据请求路径、cookies、发送的头部、查询字符串和一些自定义回调的组合来创建缓存。

...但我使用memcache(或redis)

当然,但这不是一个缓存管理系统,而只是一个存储...管理缓存需要很多知识,这不是一件容易的事情(特别是使用memcache)。

比我聪明得多的人曾经说过

在计算机科学中,只有两件困难的事情:缓存失效和命名事物。

-- Phil Karlton

您仍然可以使用memcache、redis或其他您想要的任何缓存存储系统,只需为其创建一个驱动程序并将其连接到Hrc。(请参阅下面的指南)

安装

composer require webiny/hrc

需要PHP 7.0或更高版本。

工作原理

// define cache rules
$cacheRules = [
    'FooBar' => [
        'Ttl'   => 60,
        'Tags'  => ['cacheAll'],
        'Match' => [
            'Url' => '*'
        ]
    ]
];

// where and how to store cache files
$cacheStorage = new Webiny\Hrc\CacheStorage\FileSystem('/path/to/cache/folder/');
// where and how to keep a record of all stored cache files
$indexStorage = new Webiny\Hrc\IndexStorage\FileSystem('/path/to/index/folder');
// create Hrc instance
$hrc = new Hrc($cacheRules, $cacheStorage, $indexStorage);
// store something into cache
$hrc->save('entryName', 'some content');
// retrieve something from cache
$data = $hrc->read('entryName'); // some content

1. 定义一组缓存规则

缓存规则定义了如何以及是否可以缓存某物。例如,一个简单的缓存规则看起来像这样

$cacheRules = [
    'SimpleRule'    => [
        'Ttl'   => 60,
        'Tags'  => ['simple', 'rule'],
        'Match' => [
            'Url' => '/some/*'
        ]
    ],
];

Ttl(生存时间)定义了该条目应在缓存中保留多长时间。

Tags用于标记内容,以便您可以更容易地使其失效。

Match是一组匹配标准,规则需要满足这些标准,您才能存储内容。它们还定义了用于创建缓存键的内容。

匹配标准

您可以在匹配标准中使用几个不同的东西

  • URL路径
  • 查询字符串
  • 请求头部
  • cookies
  • 自定义回调

匹配选项

  • true:参数需要存在,但只有参数名,而不是其值,将用于缓存键。
  • false:参数必须未设置,规则才能匹配。
  • *:参数需要存在,并且需要具有某些值,其值将用于缓存键。
  • ?:参数是可选的,如果存在,则其值将用于缓存键。
  • 任何PHP正则表达式 preg_match 标准
  • 任何固定字符串用于精确匹配

以下是一些匹配示例

$mockRules = [
    'AdvancedMatch' => [
        'Ttl'   => 100,
        'Tags'  => ['advanced', 'one'],
        'Match' => [
            'Url'      => '/simple/url/([\w]+)/page/([\d]+)/(yes|no)/',
            'Cookie'   => [
                'X-Cart'          => 'cart value (\d+) currency ([\w]{2})',
                'X-CacheByCookie' => 'yes'
            ],
            'Header'   => [
                'X-Cache-Me'     => 'foo (\w+)',
                'X-Cache-Header' => '*'
            ],
            'Query'    => [
                'Cache'   => true,
                'foo'     => ?
            ],
            'Callback' => [
                'Webiny\Hrc\UnitTests\CacheRules\MockCallbacks::returnValue'
            ]
        ]
    ]
];

Callback部分中,用于调用自定义回调,这基本上是对匹配规则的扩展。回调方法应返回一个值,该值将用于构建缓存键。如果回调返回布尔值false,则规则将不匹配请求。

回调方法接受两个参数,分别是Webiny\Hrc\RequestWebiny\Hrc\CacheRules\CacheRule\CacheRule

class MockCallbacks
{
    public static function returnTrue(Webiny\Hrc\Request $r, Webiny\Hrc\CacheRules\CacheRule\CacheRule $cr)
    {
        // do you thing here
    }
}

尽管不推荐,但您可以在CookieHeaderQuery上不严格指定匹配选项,而是将一个*放在那里,以简单地取所有接收到的参数(例如,所有查询参数),并为请求的任何变化构建一个缓存键。

$mockRules = [
    'GetAllParameters' => [
        'Ttl'   => 86400,
        'Tags'  => ['global', 'all'],
        'Match' => [
            'Url'      => '/match/all',
            'Cookie'   => '*',
            'Header'   => '*',
            'Query'   => '*'
        ]
    ]
];

2. 缓存存储

Hrc设计成可以存储您想要的任何存储中的缓存,从memcache到mongodb。默认情况下,我们提供了文件系统存储和MongoDb。如果您为任何其他存储机制编写了驱动程序,请发送拉取请求,我们将很乐意将其合并。

创建存储驱动程序相当简单,只需创建一个类并实现Webiny\Hrc\CacheStorage\CacheStorageInterface。您只需实现3个简单的方法即可完成任务。

3. 索引存储

索引存储用于存储额外的缓存信息,你可以将其视为缓存元数据和分类法的组合。索引主要用于实现更广泛的缓存失效功能和更快的缓存失效时间。

默认情况下,我们提供文件系统缓存索引和MongoDb缓存索引,要创建自定义的索引,只需实现Webiny\Hrc\IndexStorage\IndexStorageInterface

Mongo存储和索引

如果你计划使用Mongo缓存存储和缓存索引,确保在使用驱动程序之前运行installCollections方法,否则不会创建所需的索引,性能会变慢。

$this->cacheStorage->installCollections();
$this->indexStorage->installCollections();

你只需运行一次。另一种方法是通过手动创建两个集合和索引

  • HrcCacheStorage集合应具有以下索引
    • key => 在key字段上创建唯一索引,sparse应设置为false
    • ttl => 在ttl字段上创建索引,expireAfterSeconds设置为0秒
  • HrcIndexStorage集合应具有以下索引
    • key => 在key字段上创建唯一索引,sparse应设置为false
    • tags => 在tags字段上创建索引
    • ttl => 在ttl字段上创建索引,expireAfterSeconds设置为0秒

4. 匹配缓存规则

当你调用readsave方法时,如果你没有提供缓存规则的名称,类将遍历所有定义的缓存规则,并选择第一个与请求匹配的规则。但是,如果你提供了缓存规则名称,缓存规则匹配模式仍然必须匹配,但检查将仅针对该特定规则进行。通过提供缓存规则名称,你可以在同一HTTP请求内匹配多个缓存规则。

// use the first matched cache rule
$hrc->save('entryName', 'some content');
$data = $hrc->read('entryName');

// use fooBar cache rule
$hrc->save('block 122', 'some content', 'fooBar');
$data = $hrc->read('block 122');

5. 回调

支持两种主要的回调事件

  • beforeSave(SavePayload)
  • afterSave(SavePayload)
  • beforeRead(ReadPayload)
  • afterRead(ReadPayload)

要为这些事件注册回调,创建一个实现\Webiny\Hrc\EventCallbackInterface的类。你将不得不实现所有回调方法。两个save方法都接收1个参数,即SavePayload实例。该实例包含有关即将创建或已创建的当前缓存条目的所有相关数据。对于读取方法也是类似的,它们接收ReadPayload实例,它让你可以访问当前缓存条目以及设置清除标志的选项,这样内容实际上被清除而不是从数据库检索。

回调方法不需要返回任何内容,但由于SavePayload实例是一个对象,在beforeSave中你可以使用它来操作你的缓存条目,例如更改缓存内容、添加或删除标签等。在afterSave回调中,你会得到相同的对象,但这只是一个确认对象已成功保存。

// your Hrc instance
$hrc = new Hrc($cacheRules, $cacheStorage, $indexStorage);

// my callback handler -> must implement \Webiny\Hrc\EventCallbackInterface
$handler = new MyCallbackHandler();

// register callbacks
$hrc->registerCallback($handler); 

缓存清除

你可以通过几种方式清除缓存

通过缓存键清除

当你保存缓存条目时,保存方法将返回一个缓存键,使用该键,你可以清除该特定的条目

// save the cache and get back the cache key
$key = $hrc->save('entryName', 'some content');
// purge that cache entry
$hrc->purgeByCacheKey($key);

通过标签清除

每个缓存规则都关联一个或多个标签。使用相同的标签,你可以清除多个缓存条目。注意:在提供多个标签时,只有匹配所有标签的条目将被清除,或者换句话说,我们在标签之间使用逻辑AND条件。

$hrc->purgeByTag(['tag1', 'tag2']);

通过请求清除

你可以设置一个标志,以便当前请求中匹配的每个缓存条目都将自动被清除。

// first set the purge flag to true
$hrc->setPurgeFlag(true);

// once the flag is set to true, every `read` call, that has a cache hit, will actually do a purge
$hrc->read('entryName');

另一种方法是,在你的请求中发送一个特殊的请求头。该头是X-HRC-Purge,只需定义它,不需要设置任何值。发送该头具有将清除标志设置为true相同的效果,但这种方式不需要设置标志,并且实际上仅对特定请求有效。

安全性

基于上一节的内容,你可能认为存在很大的风险,因为每个人都可以在每次请求时清除缓存并击中你的数据库/后端...这是真的,但有一个内置的机制来防止这种情况。你可以设置一个控制键,这样只有带有有效键的请求才能通过头部清除缓存。

// set the control header
$hrc->setControlKey('someSecretString');

一旦设置了控制头部,你现在需要发送一个包含相同值的X-HRC-Control-Key请求头部。只有当这两个值匹配时,清除请求才会执行。

错误和改进

只需在问题下报告它们,或者更好的是,发送一个拉取请求:)

许可证

MIT

资源

要运行单元测试,你需要使用以下命令

$ cd path/to/Webiny/Hrc/
$ composer install
$ phpunit