SilverStripe背后的负载均衡器

时间:2017-01-09 02:48:27

标签: php caching silverstripe zend-cache elastic-load-balancer

我在AWS负载均衡器后面的两台服务器上运行了SilverStripe实例。要共享会话信息,我正在运行Elasticache Redis服务器。我正在设置我的php会话商店信息:

ini_set('session.save_handler', 'redis');
ini_set('session.save_path', 'tcp://127.0.0.1:6379');

在我登录CMS的管理部分后,我可以在服务器之间跳转并且它会记住我,但是当在CMS之间切换时,主要部分不会呈现(AJAX调用)。从我可以告诉其他服务器没有意识到(你从第二个请求的那个)你已经加载了CMS管理员,并且在响应头中说要加载新版本的JS依赖关系,然后输出管理员并且它不会加载。

阅读the docs SilverStripe正在使用Zend_Cache获取一些额外信息。我想如果我加载管理界面,然后删除它会复制问题的缓存目录。它没有。

然后我尝试使用this module来更改Zend_Cache正在使用的存储引擎。我补充说:

SS_Cache::add_backend(
    'primary_redis', 
    'Redis',
    array(
        'servers' => array(
            'host' => 'localhost', 
            'port' => 6379, 
            'persistent' => true, 
            'weight' => 1, 
            'timeout' => 5,
            'retry_interval' => 15, 
            'status' => true, 
            'failure_callback' => null
        )
    )
);
SS_Cache::pick_backend('primary_redis', 'any', 10);

对于我的mysite / _config.php,这是在密钥中存储一些cms信息,例如密钥CMSMain_SiteTreeHints9b258b19199db9f9ed8264009b6c351b,但是这仍然无法解决负载平衡环境中服务器之间的更改问题。

SilverStripe还能在哪里存储缓存数据?我是否正确实施了模块?

2 个答案:

答案 0 :(得分:2)

默认的管理界面(假设你使用的是3.x)使用​​一个名为jquery.ondemand的javascript库 - 它跟踪已经包含的文件(一种相当古老的前导类似于& #39; require.js' - 只有没有AMD,并且支持CSS。)

为此,与CMS本身有关的可能性很小 - 考虑到Web本质上是无状态的,并且您用于保存状态的方法在您的服务器之间共享(两者都是数据库和会话数据)。

HA群集中各个实例共享的是什么物理文件。这里的原因很可能(但不一定肯定)是提供给mtime的URI末尾的ondemand标记 - 最初旨在避免与主题更改有关的浏览器缓存问题(开发人员制作)或以其他方式自动化。)

毫无疑问,您正在检查的标题包括(始终,无论HAProxy,nginx,ELB或其他任何人选择的端点)X-Include-CSS和{{1} - 其中一个例子如下:

X-Include-JS [...]

这是针对每个请求,X-Include-JS:/framework/thirdparty/jquery/jquery.js?m=1481487203,/framework/javascript/jquery-ondemand/jquery.ondemand.js?m=1481487186,/framework/admin/javascript/lib.js?m=1481487181可以检查并查看已包含的内容以及需要添加的内容。

(顺便提一下,这些标头的大小是导致ondemand标头缓冲区问题导致nginx默认设置的原因。)

那么,做什么?

如果要部署静态代码,静态文件在平衡实例之间保持相同的mtime - 但这是要检查的内容。另一方面,生成的文件(例如使用502)需要在所有实例之间进行同步生成,就像您网站的所有Requirements::combine_files一样,在这种情况下,mtime应该保持不变。虽然/assets可能是一个因素,Zend_cache在这里不太可能有任何影响。当然,无论如何要检查的第一件事是我的前提是否成立 - 例如通过diff工具从两个后端运行标头响应。

答案 1 :(得分:0)

为了帮助那些可能遇到这种情况并且需要一个可以挂钩到CMS的解决方案的人,我就是这样做的:

class SyncRequirements_Backend extends Requirements_Backend implements Flushable {

    protected static $flush = false;

    public static function flush() {
        static::$flush = true;
    }

    public function process_combined_files() {
        // You can write your own or copy from framework/view/Requirements.php
        // Do the required syncing like rsync at the appropriate spot like on successfulWrite
    }
}

Requirements::set_backend(new SyncRequirements_Backend());添加到您的_config.php(我的是一个单独的扩展,但mysite也可以。)

此解决方案的问题是,如果核心Requirements_Backend更新您将运行旧版本的代码,但它不太可能破坏任何内容,您只是实现了自己的需求后端使用相同的码。您可以调用父进程而不是自己完成所有操作但是我无法找到仅在文件写入时运行同步的方法,它会在每次请求组合文件时运行。