Fi1osof
25 авг. 2013 г., 20:11

MODX Revolution + nginx + memcached.

В продолжение темы. Очень кратко опишу свой опыт с экспериментом сохранения кода страницы в memcached, который в дальнейшем уже отдает nginx без лишних запросов, получая код непосредственно из memcached.
Общая идея: генерировать страницу средствами MODX-а и сохранять ее код полностью в memcached, чтобы в дальнейшем nginx проверял наличие кода страницы в memcached-е, и если есть, отдавал код сразу, не отправляя запрос на php. Пока что это только для сайтов-визиток и т.п. (так как на таких страницах нельзя использовать логику с учетом авторизации пользователей и т.п.), но в дальнейшем планирую страницы делать полностью статическими, а всю динамику переносить на Javascript + AJAX.
Основные проблемы, с которыми столкнулся: 1. Больше всего времени потратил на настройку правил для nginx-а (свой вариант покажу ниже). 2. Битая кодировка кеша больших страниц. Как выяснилось, в php для memcached стояла настройка по умолчанию memcached.compression_threshold=2000. То есть если кешируемая строка больше 1999 символов, то php компрессирует ее. Если получить кеш средствами php, то проблем нет, он и декомпрессирует. А вот nginx за этим не следит и отдает как есть. Полечил топорно: в настройках php указал memcached.compression_threshold=9999999
Итак, код плагина:
<?php switch($modx->event->name){ case 'OnWebPageComplete': if (!empty($modx->resource) && $modx->resource->get('cacheable') && $modx->resource->get('published') && $modx->resource->_output != '' ) { $key = '/index.php?'; // Заменяем спецсимвол амперсанта $key .= str_replace('&', '&',($_SERVER['QUERY_STRING'])); // $modx->log(1, "Key: '{$key}'"); $modx->cacheManager->set($key , $modx->resource->_output); } break; default:; }
Да, плагин вешаем на событие OnWebPageComplete. Здесь мы этот момент обсуждали.
Настройка для nginx:
server { listen 80; # Указываем свой хост server_name myhost; allow all; error_log /var/log/nginx/error_log; # Указываем путь до директории сайта root /var/www/site/public_html; # Всякие запрещенные папки location ~ /\.ht { deny all; } location /core/ { deny all; } location /temp/ { deny all; } # Статика location ~* \.(jpg|jpeg|gif|png|ico|css|zip|tgz|gz|rar|bz2|doc|xls|exe|pdf|ppt|tar|wav|bmp|rtf|js)$ { access_log off; expires 30d; } # Основное правило обработки запросов location / { # файлы по умолчанию index index.php index.html; # попытка получить запрашиваемый файл в именнованной локации # Попытка - подразумевает возможные неудачи. Перечисление по порядку # в указанных вариантах. # При запросе к корню сайта будет получен индексный файл index.php, # так что сработает правило location ~ \.php$ # А правило @modx сработает только если файл не найден try_files $uri $uri/ @modx; } # Именнованная лакация (правило) location @modx { # выполняем подмену на index.php rewrite ^/(.*)$ /index.php?q=$1 last; } # Правила обработки php location ~ \.php$ { # Контент по умолчанию, чтобы нгинкс не отдавал браузеру # как обычный файл для скачивания default_type text/html; # устанавливаем ключ-переменную для запроса к мемкешу set $memcached_key "default/$uri?$args"; # выполняем запрос к мемкешу memcached_pass localhost:11211; # устанавливаем обработчик ошибок # если будет получена одна из этих ошибок, то ошибка не будет # возвращена сразу, а будет отправлен запрос дальше на php error_page 404 401 405 502 504 = @php; } location @php { # Отправляем запрос на Apache или типа того (у кого что) proxy_pass http://127.0.0.1:8888; # свой локальный порт proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $remote_addr; proxy_connect_timeout 120; proxy_send_timeout 120; proxy_read_timeout 180; } }
Напоследок хочу отметить, что в запросах учитываются все GET-параметры, так что этот метод годится и для постраничности и т.п. Любое изменение параметров запроса — это новая страница, новый кеш.
UPD: Забыл сказать, что в MODX-е еще надо сменить кеш-провайдер на memcached. По умолчанию в настройках MODX-а указано cache_handler=xPDOFileCache, то есть используется файловый кеш-провайдер. Надо поменять на cache.xPDOMemCached.
И еще момент: чтобы сразу есть настройки, которые необходимо и в сам конфиг-файл переносить. Дело в том, что для чтения системных настроек из базы данных требуется инициализация самого MODX-а. Это звучит очень логично, но не все на этом внимание заостряют. Так вот, инициализация требует предварительного чтения конфигов. И вот что получается — пока MODX не получил данные из базы данных, он использует конфиги файловые, в том числе и значения по умолчанию. А так как настройка cache_handler=cache.xPDOMemCached хранится в базе данных, то в момент инициализации MODX еще ничего о ней не знает, и соответственно использует стандартный файловый кеш-провайдер. И получив настройки из БД, он только потом очухивается, и начинает использовать Memcached. Но до этого успевает записать конфиги в файлы, и вообще каждый раз при старте читает конфиги из файлов.
Вот чтобы этого не происходило и чтобы он сразу использовал Memcached, зайди в core/config/config.inc.php и в $config_options пропиши эту настройку тоже:
$config_options = array ( "cache_handler" => "cache.xPDOMemCached", );
Вот тогда он сразу будет мемкешед юзать.
Привет.
Удали $modx->log(1, «Key: '{$key}'»); Это для отладки было.

Добавить комментарий