定制 deviateltd/silverstripe-cacheable 二次开发

按需修改功能、优化性能、对接业务系统,提供一站式技术支持

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

deviateltd/silverstripe-cacheable

Composer 安装命令:

composer require deviateltd/silverstripe-cacheable

包简介

SilverStripe page and object caching

README 文档

README

Cachable is an Object Cache for SilverStripe. It was originally designed to only cache SiteTree objects normally found in website navigation hierarchies, in order to improve site performance. Future versions aim to allow an increased range of standard SilverStripe DataObjects to be cached.

This version should work with PHP 7.2 and SilverStripe 3.7

At its core is Zend_Cache and as such the module can use the Memcache, Memcached, APCu or File Zend Backend cache's. See: code/_config.php.

Installation

  1. Git Clone
#> git clone https://github.com/deviateltd/silverstripe-cacheable.git
  1. Composer command
composer require deviateltd/silverstripe-cacheable dev-master
  1. Composer (Manual)

Edit your project's composer.json as follows:

Add a new line under the "require" block:

deviateltd/silverstripe-cacheable

Add a new block under the "repositories" block:

{
    "type": "vcs",
    "url": "https://github.com/deviateltd/silverstripe-cacheable.git"
}

Now run dev/build via the browser or command line - and don't forget to flush.

Usage

A cache is built after running the CacheableNavigation_Rebuild task. This should be run as the webserver user e.g. www-data via a crontask on your server(s):

#> sudo -u www-data /usr/bin/php path/to/framework/cli-script.php dev/tasks/ProcessJobQueueTask queue=2

A better way is to run this task natively as the www-data user by running the following and pasting the above command (without 'sudo -u') into the editor that appears - like so:

#> sudo crontask -u www-data -e

See the QueuedJobs Github wiki for more info.

This task is in itself, very memory intensive, so it can be passed some parameters to help with debugging and to improve performance:

Pass the following to restrict the cache rebuilding to just "Live" or just "Draft" items, this is useful if you know your CMS users aren't using the preview mode, or you're stress testing only the frontend:

Stage=Live
Stage=Stage

By default, the BuildTask will "chunk" your site-tree and push each chunk onto a background task using the QueuedJobs module, however, if you have no need for this, e.g. your site only has a few hundred pages, you can skip it and build the cache in one go like so:

SkipQueue=1

Note: If your site has many 100s of pages, and you attempt to run the task via the browser or with SkipQueue=1, you may exceed one or both of PHP's max_execution_time and/or memory_limit ini settings limits. The advantage of the CLI is that on some systems notably Debian-like O/S', the CLI SAPI is automatically allocated an unlimited execution time and memory limit without the need to manually call ini_set() anywhere.

If you want to boost these PHP settings as a one off for these tasks, look at PHP's -d switch that allows you to arbitrarily override settings normally set in scripts using ini_set().

Regardless, we recommend using the default mode with QueuedJobs.

Each cached object is also selectively re-built the related CMS content is published, unpublished or deleted in the CMS. See the various onAfterXX() methods in code/extensions/Cacheable.php.

Using cached objects

Out of the box, and assuming you've already built the cache, the module will handle calls to $Menu() in your templates as follows:

<% with $CachedData %>
    $Menu(1)
<% end_with %>

You can also access cache contents directly, allowing you to iterate over the entire SiteTree, use filters etc, just as though you're dealing with a standard ORM result list in your PHP logic. The following example shows how to get an SS_List of your sitetree, from the ORM or the object-cache:

/**
 * 
 * Source all items via ORM or Object cache if available and return the resulting 
 * list.
 * 
 * @return SS_List|null
 */
public function getSiteTree() {
    $list = ArrayList::create();
    $modeParts = explode('.', Versioned::get_reading_mode());
    $mode = array_pop($modeParts);
    
    if(class_exists('Cacheable')) {
        $conf = SiteConfig::current_site_config();
        $cacheService = new CacheableNavigationService($mode, $conf);
        if($cache = $cacheService->getObjectCache()) {
            $list = ArrayList::create($cache->get_site_map());
        }
    } else {
        Versioned::reading_stage($mode);
        $list = DataObject::get('Page');
    }
    
    return $list;
}

Options

By default the module will use file as its chosen cache-backend. However this can be overridden in your project's YML config. Possible values are memcache, memcached or apc:

CacheableConfig:
  # Use memcached instead of default `file`
  cache_mode: memcached

The module uses its own default "server" and "client" parameters to pass to memcached and memcache but there is some scope to override these in your project's YML config:

CacheableConfig:
  # Override module defaults for the 'server' array
  opts:
    memcached:
      servers:
        host: localhost
        port: 11212
        weight: 2
      client:
        9: 1
        2: 1
        16: true

By default the module will attempt to rebuild the cache if one doesn't exist, whenever a user hits the site. For sites with a large number of page objects this probably isn't a good idea, and you should override this in config also:

CacheableConfig:
# Instruct Cacheable not to build a cache via the "first user pays" approach
  build_cache_onload: false

Note: The cache rebuild is also skipped when a flush is in effect.

The Rebuild task can be passed a Versioned stage "Stage" or "Live" which will restrict rebuilding the cache to just the passed stage, thus:

#> sudo -u www-data ./framework/sake dev/tasks/CacheableNavigation_Rebuild Stage=Live

By default only a minimal number of class properties and methods are cached. If your project makes use of additional properties/methods, simply modify your project's config.yml file accordingly. E.g. if you had a custom field and method defined in your Page class called "WibbleField" and "getWibble", you could instruct the module to cache them thus:

CacheableSiteTree:
  cacheable_fields:
    - WibbleField
  cacheable_functions:
    - getWibble

Similarly you do the same for your custom site config, via CacheableSiteConfig.

Out of the box when using the "file" backend, Cacheable will store its object cache files in a directory called "cacheable" under SilverStripe's temp folder. However in some circumstances such as when using the Deploynaut deployment system, SilverStripe's temp directory is deleted and re-created, thus truncating your cache entirely. In this case, you can use the alt_cache_dir option in your YML config, which specifies an alternate location that Deploynaut will leave alone:

Note: Any custom directory locations are always made relative to the assets directory. This makes the cache portable on those platforms that replicate / duplicate database and assets onto other VM's or bare metal.

Instruct Cacheable to build the cache under: assets/_foo/bar/cacheable:

CacheableConfig:
  alt_cache_dir: 'foo/bar'

Instruct Cacheable to build the cache under: assets/_cacheable:

CacheableConfig:
  alt_cache_dir: cacheable

Cache inspector

If you have CMS admin access, you can request a specific URL to inspect the state of your caches. The URI is: /cacheable/inspector and it provides the following information:

  • No. Cached objects vs Database derived totals - useful for debugging
  • The backend currently in-use
  • Cache file-listing, no. files, total cache disk usage, cache last-updated time etc ("File" backend only)

Known issues

Sites that utilise controller-only "Pages" aren't necessarily related to a SiteTree object and therefore will have no entry to reference in the object-cache. In these instances e.g. /admin/login we default to using the homepage's cache-entry.

FAQ

Q: Why the references to "CacheableNavigation" all over the place?

A: The module was originally designed to cache mega/side/footer menu's which source their list data from the SilverStripe $Menu() method as these site-areas are usually the biggest performance killers on any moderately sized SilverStripe site. These references will be gradually refactored out and the module made more generic.

Q: How does this module compare with SilverStripe's Partial Caching feature?

A: A full performance comparison methodology has been prepared, and we await the results. However, Cacheable improves over Partial Caching in that, there's never one user who needs to bare the overhead of priming the cache (1). With Cacheable this is done via a BuildTask with the added bonus of avoiding that rare beast the Cache Stampede.

Q: How does this module compare with a site without it, but with an Opcode Cache running?

A: A full performance comparison methodology has been prepared, and we await the results.

Footnotes

  1. This is only true when your project overrides default module behaviour, like so:

    CacheableConfig:

    Instruct Cacheable not to build a cache via the "first user pays" approach

    build_cache_onload: false

deviateltd/silverstripe-cacheable 适用场景与选型建议

deviateltd/silverstripe-cacheable 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 2.75k 次下载、GitHub Stars 达 6, 最近一次更新时间为 2015 年 05 月 07 日, 在 PHP 生态内属于活跃度较高的组件。

它主要适用于以下技术方向: 「cache」 「caching」 「object」 「silverstripe」 「cacheable」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。

我们在过去多个企业项目中使用过 deviateltd/silverstripe-cacheable 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。

围绕 deviateltd/silverstripe-cacheable 我们能提供哪些服务?
定制开发 / 二次开发

基于 deviateltd/silverstripe-cacheable 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。

BUG 修复 & 性能优化

线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。

项目外包 & 长期维护

承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。

yvsm@zunyunkeji.com QQ:316430983 微信:yvsm316 西安尊云信息科技 · 专注 PHP / Go / 分布式系统研发

统计信息

  • 总下载量: 2.75k
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 6
  • 点击次数: 13
  • 依赖项目数: 0
  • 推荐数: 0

GitHub 信息

  • Stars: 6
  • Watchers: 3
  • Forks: 2
  • 开发语言: PHP

其他信息

  • 授权协议: Unknown
  • 更新时间: 2015-05-07