У меня есть экземпляр 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, минимальна – учитывая, что веб по своей природе является апатридом и что метод, который вы используете для сохранения состояния, используется на всех серверах (как базы данных, так и данные сеанса) ,
То, что не разделяется между отдельными экземплярами вашего кластера HA, – это физические файлы. Причина здесь, скорее всего, (но не обязательно) – быть 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
может быть фактором. Конечно, первое, что нужно проверить в любом случае, заключается в том, действительно ли моя предпосылка верна – например, для запуска ответов заголовков с обоих сторон через инструмент diff.
Чтобы помочь тем, кто может столкнуться с этим, и нужно решение, которое подключается к 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 тоже будет работать).
Проблема с этим решением заключается в том, что если в Core Requirements_Backend вы будете использовать более старую версию кода, но вряд ли что-то сломает, вы только что внедрили свой собственный бэкэнд требований, который использует тот же код. Вы могли бы просто вызвать родителя вместо того, чтобы все это делать самостоятельно, но я не мог найти способ запуска синхронизации только при записи файла, он будет запускаться каждый раз, когда будет запрошен комбинированный файл.