【问题标题】:SilverStripe behind load balancer负载均衡器后面的 SilverStripe
【发布时间】:2017-01-09 02:48:27
【问题描述】:

我有一个 SilverStripe 实例在 AWS 负载均衡器后面的两台服务器上运行。为了共享会话信息,我正在运行 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,这是在 redis 中存储一些 cms 信息,例如密钥 CMSMain_SiteTreeHints9b258b19199db9f9ed8264009b6c351b,但这仍然不能解决负载平衡环境中服务器之间更改的问题。

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

【问题讨论】:

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


    【解决方案1】:

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

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

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

    毫无疑问,您检查的标头包括(总是,无论 HAProxy、nginx、ELB 或其他选择的端点)X-Include-CSSX-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 标头缓冲区问题的原因,导致 502 在“默认”设置中。)

    那么,怎么办?

    如果您正在部署静态代码,则静态文件应该在平衡实例之间保持相同的 mtime - 但这是需要检查的。另一方面,生成的文件(例如Requirements::combine_files)需要在所有实例之间(重新)生成时同步,就像您站点的所有/assets 一样,在这种情况下,mtime 应该保持不变。 Zend_cache 不太可能在这里产生任何影响,尽管 APC 可能是一个因素。当然,在任何情况下首先要检查的是我的前提是否成立 - 例如通过差异工具从两个后端运行标头响应。

    【讨论】:

    • 这有点道理,我目前正在同步上传资源。有没有可以挂钩组合文件的功能?
    • 就是这样,在系统上运行 rsync 复制了 _combinedfiles,管理员又开始工作了。
    • 我不确定您如何实现它 - 可能使用像 csync2 这样的工具,但设置文件系统监视以启动同步(或者可能只是有一个计划任务/ cron 作业每秒运行一次左右)。
    • 我想通了并在下面发布了答案。
    【解决方案2】:

    为了帮助那些可能遇到此问题并需要与 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 更新您将运行旧版本的代码,但它不太可能破坏任何内容,您刚刚实现了使用相同代码的自己的需求后端。您可以只调用父级而不是自己完成所有操作,但是我找不到仅在文件写入时运行同步的方法,它会在每次请求组合文件时运行。

    【讨论】:

      猜你喜欢
      • 2017-06-12
      • 2013-10-12
      • 1970-01-01
      • 2021-12-07
      • 2017-05-25
      • 2018-03-24
      • 2015-06-17
      • 2011-01-10
      • 1970-01-01
      相关资源
      最近更新 更多