У меня есть экземпляр 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-зависимостей, которая затем выводит администратора и его не загружается
Чтение в документы SilverStripe использует Zend_Cache для получения дополнительной информации. Я полагаю, что если я загружу интерфейс администратора, то удаляю каталог кеша, это повторяет проблему. Это не так.
Затем я попытался использовать этот модуль изменить механизм хранения, который использует 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 в Redis, как для ключа CMSMain_SiteTreeHints9b258b19199db9f9ed8264009b6c351b
однако это по-прежнему не решает проблему переключения между серверами в среде с балансировкой нагрузки.
Где еще SilverStripe может хранить данные кэша? Правильно ли реализован модуль?
Стандартный интерфейс администратора (при условии, что вы используете 3.x) использует библиотеку javascript, которая называется jquery.ondemand
— это отслеживает файлы, которые уже были включены (довольно древний вид предшественников вроде ‘require.js
‘- только без AMD и с поддержкой CSS).
С этой целью вероятность того, что это как-то связано с самой CMS, минимальна — учитывая, что сеть по своей природе не имеет состояния и что метод, который вы используете для сохранения состояния, является общим для ваших серверов (как базы данных, так и данных сеанса) ,
Что такое не общие для отдельных экземпляров в вашем кластере высокой доступности являются физическими файлами. Причина здесь, вероятно, (но не обязательно) будет mtime
печать на конце URI, предоставленных ondemand
— изначально предназначен для того, чтобы избежать проблем с кэшированием в браузере в отношении изменений темы (разработчик сделал или иным образом автоматизировал).
Заголовки, которые вы без сомнения проверяли, включают (всегда, независимо от конечной точки, выбранной HAProxy, nginx, ELB или чем-либо еще) X-Include-CSS
а также 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
проблемы с буфером заголовка, вызывающие 502
в настройке «по умолчанию».)
Статические файлы должен сохраняйте одно и то же время между сбалансированными экземплярами, если вы развертываете статический код — но это кое-что нужно проверить. Сгенерированные файлы с другой стороны (например, с Requirements::combine_files
) нужно будет синхронизировать (пере) генерацию между всеми экземплярами, как со всеми /assets
для вашего сайта, в этом случае mtime должен сохраняться. Zend_cache
здесь вряд ли что-то повлияет, хотя APC
может быть фактором. Конечно, первое, что нужно проверить в любом случае, это то, верно ли мое предположение — например, запустить ответы заголовка от обоих бэкэндов через инструмент сравнения.
Чтобы помочь тем, кто может столкнуться с этим и нуждается в решении, которое подключается к 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 обновляет, вы будете использовать более старую версию кода, однако вряд ли что-то сломается, вы только что внедрили свой собственный бэкэнд требований, использующий тот же код. Вы можете просто позвонить родителю, а не делать все самостоятельно, однако я не смог найти способ запустить синхронизацию только при записи в файл, он будет запускаться каждый раз, когда запрашивается объединенный файл.