УрокОтдаём кэш анонимов без поднятия бэкэнда. Drupal 7 + nginx + memcached.

Помните статью о снижении нагрузки с помощью Memcache Storage? Там Drupal отдавал анонимам кэш на второй фазе бустрапа, что существенно снижало нагрузку на сайт, особенно его посещали преимущественно анонимные пользователи. Там отдача страницы происходила за 50-70мс. Однако я решил этим не ограничиваться, и отдавать кэш вообще без поднятия бэкэнда (на большинстве хостингов это apache). Таким образом мало того, что отдача страницы происходит в десятки раз быстрее, так ещё и не расходуется память на новые процессы апача (или любого другого бэкэнда).

Чтобы понимать, что происходило раньше при отдаче страниц анонимам (по материалам этой статьи), я накидал небольшую схему:

  1. Клиент вбивает определённый урл в браузер
  2. Запрос на отдачу страницу по этому урлу направляется на nginx
  3. Nginx видит, что запрос динамический, и передаёт его дальше на сторону apache
  4. Apache запускает index.php сайта и начинается фаза бутстрапа в Друпале
  5. В бутстрапе проверяется – если пользователь аноним, то можно попробовать поискать для него текущую страницу в мемкэше
  6. Если кэш есть – HTML страница отдаётся пользователю и завершается выполнение запроса.
  7. Если кэша нет – Друпал начинает полную загрузку и рендер страницы (соединение с базой данных, загрузку блоков страницы, поднятие слоя темизации и так далее).
  8. По завершению выполнения загрузки страницы, она в отрендеренном виде складывается в мемкэш и показывается пользователю.

Последний пункт означает, что при следующей загрузке этой страницы (пока не истечёт срок годности кэша) пользователь дойдёт только до 6го пункта этого списка, избежав тяжеловесных операций.

Давайте посмотрим на эту схему более наглядно. Вот так выглядит обычный алгоритм обработки запроса, если страница не закэширована:

drupal_default.jpg

Наверняка, эта схема всем вполне знакома и понятна. Ещё одна достаточно знакомая схема - когда используется Memcache Storage и при загрузке текущей страницы для неё был найден кэш:

drupal_memcached.jpg

Схема, безусловно, хороша. Однако я предлагаю эту схему усовершенствовать (при условии, что кэш для текущей страницы есть) до следующей:

drupal_memcached_nginx.jpg

Теперь алгоритм выполнения запроса будет следующий:

  1. Как и раньше, клиенту сначала придётся вбить определённый урл в браузер
  2. Запрос всё так же будет передан на nginx
  3. Nginx проверяет, можно ли искать данную страницу в кэше. Если да, то он самостоятельно делает запрос в мемкэш и пытается оттуда получить HTML для текущей страницы.
  4. При успешном завершении поиска страницы в кэше – она сразу же показывается пользователю, и на этом обработка запроса завершается.
  5. Если кэша нет, то далее следуют пункты 4, 7 и 8 из предыдущего списка.

То есть по сути, мы вообще отдаём пользователю страницу не прибегая к выполнению ни одной строки PHP кода!

Для настройки этой высокопроизводительной связки нам потребуется немного поковыряться в настройках. Давайте перейдём непосредственно к ним.

Конфигурация Memcache Storage

Во-первых, вам надо скачать последнюю версию Memcache Storage 7.x-1.2, т.к. интеграцию туда я добавил совсем недавно.

Во-вторых, вот такие настройки в settings.php необходимы для корректной интеграции:

# Move all cached data (except form cache) to memcache storage.
$conf['cache_backends'][] = 'sites/all/modules/memcache_storage/memcache_storage.inc';
$conf['cache_default_class'] = 'MemcacheStorage';
$conf['cache_class_cache_form'] = 'DrupalDatabaseCache';
 
# Advanced usage of Drupal page cache.
$conf['cache_backends'][] = 'sites/all/modules/memcache_storage/memcache_storage.page_cache.inc';
$conf['cache_class_cache_page'] = 'MemcacheStoragePageCache';
 
# Enable storing of plain HTML text instead of Drupal usual cache object.
$conf['memcache_storage_external_page_cache'] = TRUE;


Конфигурация Memcached

Особо вдаваться в подробности не буду, я уже писал про качественную настройку демона memcached, она здесь отлично подойдёт.

Единственное, на чём хотелось бы заострить внимание – я настоятельно рекомендую выносить кэш страниц в отдельную сущность мемкэша. Ниже я написал, почему это необходимо.

Также напоминаю, что наибольшую производительность в интеграции с memcached можно получить имея pecl memcached 2.0.1+ и используя сокеты вместо tcp/udp соединения.


Конфигурация Nginx

Наконец мы подошли к самому интересному – конфигам nginx. Я дописывал интеграцию сразу в конфиг под Друпал, поэтому выкладываю как есть. В комментариях я подробно расписал за что каждая часть отвечает:

server {
 
  # Слушаем 80й порт, чтобы запрос сразу попадал на Nginx.
  listen 80;
 
  # Указываем корневую директорию сайта.
  root /var/www/example.com;
 
  # Указываем урл сайта.
  server_name www.example.com;
 
  # Включаем поддержку SSI.
  # Для взаимодействия Nginx + Memcached это не надо, однако эта технология
  # очень может помочь при отображении динамических блоков на кэшированных страницах.
  ssi on;
  ssi_silent_errors on;
 
  # Полностью закрываем доступ к директориям приватной системы.
  location ~ ^/sites/.*/private/ {
	return 403;
  }
 
  # Закрываем доступ к скрытым файлам и директориям, чьё название начинается
  # с точки. Это правило включает в себя директории, используемые системами
  # контроля версий (Git, Svn и тд).
  location ~ (^|/)\. {
	return 403;
  }
 
  # Это правило обрабатывает путь к изображениям, генерируемым с помощью
  # пресетов в Друпале. Сначала пытаемся отдать файл с помощью Nginx, а если
  # файл не найден, то передаём запрос на бэкэнд для генерации изображения.
  location ~ /sites/.*/files/styles/ {
	try_files $uri @backend;
	expires 30d;
	log_not_found off;
  }
 
  # Весь статический контент также отдаём с помощью Nginx.
  # Если файл не найден - то Nginx отдаст 404 ошибку. Это достаточно
  # классная фича, т.к. большое кол-во 404 страниц может серьёзно навредить производительности.
  # Кстати, с этими строками больше нет неоходимости в drupal_fast_404().
  location ~* \.(png|gif|jpg|jpeg|css|js|ico|swf|flw|cgi|bat|pl|dll|exe|asp)$ {
	try_files $uri =404;
	expires 30d;
	log_not_found off;
  }
 
  # Сюда должны попадать только динамические запросы.
  location / {
 
	# Сюда будут направлены запросы, которые не удовлетворяют нашим условиям.
	# Кстати, по поводу условий есть одна очень интересная статья:
	# http://wiki.nginx.org/IfIsEvil. Прочитав её вы поймёте, почему здесь
	# я использовал данную конструкцию.
	error_page 418 = @backend;
 
	# Если пользователь авторизован - сразу передаём запрос на бэкэнд.
	if ($http_cookie ~* "SESS") {
  	return 418;
	}
 
	# Если запрос не GET или HEAD, то также передаём запрос дальше.
	if ($request_method !~ ^(GET|HEAD)$ ) {
  	return 418;
	}
 
 	# Выставляем заголовок для отображения HTML, т.к. кроме нас его
	# больше будет некому выставить (обычно это делает бэкэнд, но сейчас
	# до него запрос не дойдёт).
	default_type text/html;
 
	# Если страница будет найдена в кэше, то выставится вот такой заголовок.
	# Он не несёт в себе никакой нагрузки, это больше для отладки работы
	# связки в браузере.
	add_header X-Nginx-Page-Cache HIT;
 
	# Ищем текущую страницу в мемкэше. Данную строку желательно оставлять без изменений.
	# Если вы используете префикс в настройках Memcache Storage, то перед cache_page добавьте
	# префикс с дефисом. Выглядеть это будет так:
	# set $memcached_key "PREFIX-cache_page-$scheme://$server_name$uri$is_args$args";
	set $memcached_key "cache_page-$scheme://$server_name$uri$is_args$args";
 
	# Здесь указываете адрес memcached сервера. Как видите, и здесь можно использовать сокеты.
	# Подробнее про это можно почитать тут http://nginx.org/ru/docs/http/ngx_http_memcached_module.html
	# Очень классной фичей является то, что здесь можно использовать upstream'ы.
	memcached_pass unix:/var/run/memcached/memcached.socket1;
 
	# Если кэш не был найден в мемкэше - передаём запрос бэкэнду.
	proxy_intercept_errors on;
	error_page 404 502 = @backend;
  }
 
  # Передача запроса на сторону Apache.
  location @backend {
 
	# Выставляем заголовок, что не получилось вытянуть кэш
	# из мемкэша. Опять же - он просто для отладки и его можно убрать.
	add_header X-Nginx-Page-Cache MISS;
 
	# Отправляем запрос апачу на порт 8080, который он должен слушать.
	proxy_pass         	http://www.example.com:8080/;
	proxy_connect_timeout   120;
	proxy_send_timeout 	120;
	proxy_read_timeout 	180;
 
	# Заголовки, которые будут переданы апачу.
	proxy_set_header  Host              	$host;
	proxy_set_header  X-Real-IP         	$remote_addr;
	proxy_set_header  X-Forwarded-For   	$proxy_add_x_forwarded_for;
  }
}

Настоятельно рекомендую внимательно прочитать все комментарии в конфиге, т.к. в них раскрывается его сакральный смысл.

Теперь давайте рассмотрим плюсы такой интеграции:

  • Нагрузка для анонимных пользователей снижается фантастически - отдача страницы происходит за несколько милисекунд.
  • Масштабируемость. Данное решение сохраняет все преимущества масштабирования мемкэша. Правда, в этом случае надо будет немного допилить конфиг (настроить апстримы), однако это делается слишком просто, поэтому за проблему не считается.
  • У вас есть статистика по использованию памяти в мемкэше (например, phpMemcachedAdmin). При необходимости вы сможете покопаться там и подебажить хранимые страницы, “пощупать” как оно лежит в оперативной памяти.
  • Вы можете настраивать кэш страниц как вам удобно, используя все доступные для этого модули Друпала. Например, интеграция с Cache Expiration может сделать эту связку неимоверно эффективной.
  • Вы можете легко самостоятельно управлять кэшем страниц через стандартные функции ядра для работы с кэшем. Это даёт немаловажную возможность тонкой настройки работы с кэшированными страницами.
  • Пожалуй, самое минимальное время отдачи страницы. Ещё в прошлом году Ромка писал, цитирую “Думаю, посоперничать в производительности с Варнишем могло бы только решение со сязкой nginx + memcache, о которой я говорил выше, но такого готового решения под Друпал нет и в условиях постоянной нехватки времени Варниш является максимально удобным решением по соотношению скорость работы / скорость внедрения.” Собственно, вуа-ля.
  • Наиболее рациональное использование памяти, по сравнению с другими аналогами. Любое перемещение файлового кэша в оперативную память, безусловно, даёт преимущество. Однако мне даже сложно сравнивать этот вариант, со специально заточенной под это системой, с продуманной фрагментацией памяти, заточенной под максимальную скорость отдачи.

Конечно, эта связка имеет и свои недостатки. Они, как и преимущества, заключаются в архитектуре мемкэша:

  • Нет возможности очистки по wildcard. То есть я не могу очистить страницы, которые начинаются, например, на news*. Это связано с тем, что мемкэш этого просто не поддерживает. Внутри Друпала это можно обработать, сделав проверку на указанные wildcard’ы после получения кэша. Однако на стороне nginx это сделать невозможно. Поэтому если вы хотите удалить большое количество страниц, вам придётся для каждой страницы вызвать cache_clear_all() отдельно. Это не большая проблема (т.к. работает быстро), но это надо учитывать при построении архитектуры с данной связкой.
  • Теряется фича с очисткой всего хранилища {cache_page}. Снова из-за того, что мемкэш не поддерживает очистку по wildcard. Это связано с тем, что когда кэш используется внутри Друпала, то мы можем проворачивать некоторые финты ушами, которые помогают имитировать сброс кэша. А вот nginx этого уже сделать не может. Однако и здесь есть свой выход - создавать отдельный инстанс мемкэша под кэш страниц. В конфиге мемкэша, который я уже ранее выкладывал, это сделано . Таким образом, вы снова сможете сбрасывать весь кэш страниц при необходимости.
  • Очевидный минус - это сложность в настройке. Моя оценка может быть несколько субъективной, но мне всё же кажется, что у неопытного разработчика настройка связки nginx + memcached с незаурядной конфигурацией может вызвать некоторые затруднения.
  • Простые хостинги это решение не потянут, т.к. оно серьёзно затрагивает серверную конфигурацию.

Вот так эта связка выглядит для меня. Очевидно, что для больших проектов это далеко не единственное улучшение, которое придётся сделать. Скорее всего придётся подключить SSI для блоков, которые надо отображать в реальном времени, не взирая на кэш. Скорее всего, придётся устанавливать модули, которые помогут использовать механизм кэширования страниц на полную катушку. Однако это не является темой данной статьи.

Напоминаю, что данный метод не является средством оптимизации сайта. Это хороший инструмент в снижении нагрузки, и это важно понимать. С такой связкой не страшен даже хаброэффект. А если немного подкрутить конфиг - то можно даже отдавать страницу из кэша и для авторизованного пользователя если, например, бэкэнд упал (это очень напоминает одну из фич варниша).


Почему не нативный кэш nginx?

Я неоднократно слышал вопрос - “почему ты просто не использовал нативный кэш nginx?”. Я думаю, что ответ кроется в 2-7 пунктах из “плюсов” связки. Разве нативный кэш nginx может это превзойти, или хотя бы повторить эти преимущества? Для меня ответ очевиден.


Похвали себя сам

В конце статьи я хотел бы обратить внимание на то, что, судя по всему, я оказался первым, кто сделал подобную связку. Вот почему мне так кажется:

  • В гугле нет подобного материала по запросу drupal + memcached + nginx. Есть просто включение мемкэша рядом с настройкой nginx, но никаких намёков на интеграцию между ними.
  • Раньше был только один модуль, позволяющий интегрировать Друпал с мемкэшем - и это Memcache API. Однако он хранит в мемкэше кэш в виде сериализованных объектов, а nginx не умеет десериализовывать данные и использовать php объекты. Можно, конечно, скомпилировать nginx с поддержкой perl сниппетов и попробовать дописать эту недостачу, однако такого решения я также не нашёл.

Упоминание про новую связку в интеграции с Друпалом здесь не просто так. Я веду к тому, что вы будете фактически первоиспытателями этой связки в Друпале, и информацию по этому вопросу искать в интернете бесполезно - придётся задействовать соображалку :)

Комментарии

Аватар пользователя varnish_fun
varnish_fun написал:

а если вместо nginx использовать varnish?

01.09.2013 22:32
Аватар пользователя varnish_fun
varnish_fun написал:

в смысле varnish +memcache

01.09.2013 22:41
Аватар пользователя Spleshka
Spleshka написал:

Не вижу принципиальной разницы. Просто nginx + apache - наиболее распространённая связка, вот я под nginx и написал конфиг. Можно тоже самое сделать и под varnish. Тут основной идеей было научить друпал складывать кэш страниц в мемкэш в виде текста, а не сериализованных объектов.

01.09.2013 23:03
Аватар пользователя varnish_fun
varnish_fun написал:

а ежели на сервере мало оперативки?
Это я к тому ,что варниш умеет хранить свой кеш и в памяти и в файловой системе
можно обойтись одним варнишем без мемкеша - вообщем вариантов масса
только как подобрать оптимальный?
mecache во-первых, начинает терять данные на высокой нагрузке, во-вторых, не предназначен для хранения больших объёмов данных
также можно рассмотреть и редис

01.09.2013 23:31
Аватар пользователя Spleshka
Spleshka написал:

@varnish_fun,

Ну смотря что значит мало. 512мб вполне хватит для сайта внушительных размеров. Я считал - если взять за средний размер страницы 70кб, то туда влезет около 7.5 тысяч страниц.

Безусловно, любой из вариантов годен. Использовать варниш в качестве реверсивного прокси можно, и тогда уже по большому счёту без разницы где хранится кэш - на диске или в памяти. Просто я предлагаю уже готовое решение под Друпал, с поддержкой всех модулей, управляющих кэшем страниц. Под варниш тоже, кстати, можно использовать модуль Cache Expiration для очистки страниц из кэша.

Оптимальная подборка строится из ваших серверных конфигураций и требований сайта, общей рекомендации дать не смогу.

>> mecache во-первых, начинает терять данные на высокой нагрузке
>> во-вторых, не предназначен для хранения больших объёмов данных

Кто вам сказал этот бред? Он прекрасно используется, например, вконтакте и на фэйсбуке. Разве там маленький объём данных?

02.09.2013 12:08
Аватар пользователя Master
Master написал:

Отличный метод!
Но годиться, к сожалению, далеко не для всех страниц. Например как это будет работать с формой комментариев, или банерной? Полагаю никак :)
Так же возникнут проблемы со статистикой просмотров страниц и другими "фенечками" Друпала выполняемые через hook_exit. Нуден механизм дёрнуть этот самый хук в друпале в любой сохранённой странице. Поправьте, если не прав.

04.09.2013 18:31
Аватар пользователя Spleshka
Spleshka написал:

Почему это не будет работать с формой комментариев? Всё будет фунициклировать как и положено.
Банерную систему в таких случаях я внедрял с помощью SSI, тоже проблем не возникало.
Конечно, hook_exit() не будет работать, и соответственно, считаться кол-во просмотров. Но всё это можно реализовать либо на SSI, либо на JS, это совсем не сложно. Такое решение того стоит :)

05.09.2013 10:12
Аватар пользователя Master
Master написал:

Форма коментариев с капчей????

05.09.2013 11:58
Аватар пользователя Spleshka
Spleshka написал:

Сказать, как сделать, или в чём вопрос? :)

06.09.2013 14:40
Аватар пользователя che
che написал:

Да, было бы очень полезно )

04.03.2016 00:59
Аватар пользователя includer
includer написал:

А почему Вы делаете акцент на memcache?
Ведь в памяти можно хранить и с помощью того же apc ,который к тому же присутствует на многих шаред хостингах
в чем преимущество мемкеша перед другими key-value хранилищами?

05.09.2013 20:32
Аватар пользователя Spleshka
Spleshka написал:

Мне нравятся инструменты для работы с мемкэшем (например, тот же phpMemcachedAdmin). Мне нравится его простая и удобная масштабируемость. Мне нравится то, что я полностью знаю его архитектуру. Мне нравится то, что для него написана интеграция со всем, чем нужно. Мне нравится как он фрагментирует память. Мне нравятся его алгоритмы работы при заполненной памяти. Мне нравится подробная и доступная документация. Я могу продолжать достаточно долго :)

06.09.2013 14:46
Аватар пользователя Master
Master написал:

ключевое - "Мне нравится то, что я полностью знаю его архитектуру"

06.09.2013 15:58
Аватар пользователя Spleshka
Spleshka написал:

1. С чего ты взял, что ключевое? Я изучил архитектуру, потому что мне понравилось реализация.
2. Любой выбор использования какого-либо компонента всегда вызовет вопрос "Почему это, а не то?". Выбор компонента решается при выполнении определённых задач и архитектурных задумок.
3. На данный момент для моих задач по совокупности критериев побеждает мемкэш, поэтому и статьи про него пишутся. Понадобится ещё что-то - будут другие статьи :)

06.09.2013 17:41
Аватар пользователя Валентин Будкин
Валентин Будкин написал:

Spleshka, не можете ли посоветовать специалиста, который переведёт кэширование из MongoDB в memcache storage?

Устал уменьшать размер файлов Mongo.

19.09.2013 12:35
Аватар пользователя Spleshka
Spleshka написал:

А в чём проблема с переносом кэша? Просто переписать пару строк кода в settings.php и всё. Примеры этих строк есть в README.txt модуля memcache_storage. Если есть вопросы - спрашивайте, помогу.

19.09.2013 15:37
Аватар пользователя zenon
zenon написал:

Убрать отсюда апач и всё будет намного лучше...

02.10.2013 01:02
Аватар пользователя Энди
Энди написал:

Какой формат у memcache?

12.10.2013 02:58
Аватар пользователя Spleshka
Spleshka написал:

Не понятен вопрос. Какой ещё формат?

14.10.2013 16:50
Аватар пользователя Chess
Chess написал:

поднимаю связку nginx-memcache
вроде все сделал по статьям но nginx отдает кашу когда страницу отдает от memcached, т.е.
X-Nginx-Page-Cache HIT - каша
при первом
X-Nginx-Page-Cache MISS - все ок

06.11.2013 17:41
Аватар пользователя Spleshka
Spleshka написал:

убери сжатие кэшированных страниц в настройках друпала

07.11.2013 21:26
Аватар пользователя dl
dl написал:

Была такая же трабла. Отключил сжатие. Для одной страницы - помогло. Другая же, почему-то так и осталась - из кэша как попало отображаться :( А так очень интересно - попробую еще поковырятся.

23.01.2015 13:31
Аватар пользователя Andrew
Andrew написал:

А есть возможность портировать Ваш модуль на 6.х?

20.11.2013 02:42
Аватар пользователя xurshid
xurshid написал:

у меня тоже проблема с .gz файлами.. Как можно решить такую проблему? это происходить когда активирована опция .gz с мод. Advagg..

28.12.2013 16:28
Аватар пользователя Plague
Plague написал:

Очень интересно ваше решение. Прошу кратко объяснить как сделать так, чтобы необходимые блоки на страницах не кешировались, или время жизни кеша отдельных блоков было минимальным около 5 минут. Также интересно как сохранить возможность вести статистику просмотров страниц. Это необходимо для новостного сайта.
Огромное спасибо!

29.01.2014 14:30
Аватар пользователя chilic
chilic написал:

Для того чтобы не кешировать отдельные блоки можно использовать SSI (nginx), либо ESI (varnish)

19.02.2014 17:54
Аватар пользователя tamonten
tamonten написал:

отключил adBlock , тыкнул на рекламу. Большое спасибо за статью

09.02.2014 01:17
Аватар пользователя Михаил
Михаил написал:

Евгений, спасибо за модуль!
Главная проблема в связке с nginx - это конечно отсутствие возможности очистки кэша по wildcards.
В моем случае не хватает очистки кэша страниц пейджеров (?page=N). Не планируете ли добавить такую функцию в Cache Expiration?

20.04.2014 21:06
Аватар пользователя Михаил
Михаил написал:

Вопрос снимается.
Нашел Cache expiration API, решил сам:

function MYMODULE_expire_cache($urls, $wildcards, $object_type, $object) {
  foreach ($urls as $url) {
    cache_clear_all($url, 'cache_page');
    //watchdog('cache_expire', $url);
    if (in_array($object_type, array('node', 'comment'))) {
      if (substr_count($url, 'node') || substr_count($url, 'taxonomy/term')) {
        continue;
      }
      for ($i = 1; $i < 100; $i++) {
        $cid = $url .'?page='. $i;
        cache_clear_all($cid, 'cache_page');
        //watchdog('cache_expire', $cid);
      }
    }
  }
}
20.04.2014 23:24
Аватар пользователя DANic
DANic написал:

Добрый день.
Не могу разобраться почему у меня никак не отдает страницы из кэша.
Использую связку nginx + php-fpm + memcached
Модуль установлен и работает судя по отчету корректно
[IMG]http://my.jetscreenshot.com/21512/m_20140512-oy0y-26kb.jpg[/IMG]
Сокет memcached существует

Конфиг Nginx такой

server {
  server_name www.itechinvest.ru;
  rewrite (.*) http://itechinvest.ru$1;
}
 
server {
  listen 80;
  server_name itechinvest.ru;
 
  access_log /var/log/nginx/itechinvest.access.log;
  error_log /var/log/nginx/itechinvest.error.log;
 
  ssi on;
  ssi_silent_errors on;
 
  root /var/www/itechinvest.ru;
 
  # Полностью закрываем доступ к директориям приватной системы.
  location ~ ^/sites/.*/private/ {
        return 403;
  }
 
  # Закрываем доступ к скрытым файлам и директориям, чьё название начинается
  # с точки. Это правило включает в себя директории, используемые системами
  # контроля версий (Git, Svn и тд).
  location ~ (^|/)\. {
        return 403;
  }
 
  # Это правило обрабатывает путь к изображениям, генерируемым с помощью
  # пресетов в Друпале. Сначала пытаемся отдать файл с помощью Nginx, а если
  # файл не найден, то передаём запрос на бэкэнд для генерации изображения.
  location ~ /sites/.*/files/styles/ {
        try_files $uri @drupal;
        expires 30d;
        log_not_found off;
  }
 
  #Для работы скриптов update.php authorize.php
  location ~ \.php$ {
     fastcgi_pass   unix:/var/run/php5-fpm.sock;
     fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
     include        fastcgi_params;
  }
 
  # Весь статический контент также отдаём с помощью Nginx.
  # Если файл не найден - то Nginx отдаст 404 ошибку. Это достаточно
  # классная фича, т.к. большое кол-во 404 страниц может серьёзно навредить производительности.
  # Кстати, с этими строками больше нет неоходимости в drupal_fast_404().
 
  location ~* \.(png|gif|jpg|jpeg|css|js|ico|swf|flw|cgi|bat|pl|dll|exe|asp|ttf)$ {
        try_files $uri =404;
        expires 30d;
        log_not_found off;
  }
 
  #Alias на форум phpbb
  location ^~ /forum {
    alias /var/www/forum;
    index index.html index.htm index.php;
        location ~ \.php$ {
         fastcgi_pass unix:/var/run/php5-fpm.sock;
         fastcgi_index index.php;
         include fastcgi_params;
         fastcgi_param SCRIPT_FILENAME $request_filename;
         fastcgi_ignore_client_abort off;
       }
  location / {
#       try_files $uri @drupal;
        error_page 418 = @drupal;
 
        # Если пользователь авторизован - сразу передаём запрос на бэкэнд.
 
        if ($http_cookie ~* "SESS") {
        return 418;
        }
 
        # Если запрос не GET или HEAD, то также передаём запрос дальше.
 
        if ($request_method !~ ^(GET|HEAD)$ ) {
        return 418;
        }
 
        # Выставляем заголовок для отображения HTML, т.к. кроме нас его
        # больше будет некому выставить (обычно это делает бэкэнд, но сейчас
        # до него запрос не дойдёт).
 
        default_type text/html;
 
        # Если страница будет найдена в кэше, то выставится вот такой заголовок.
        # Он не несёт в себе никакой нагрузки, это больше для отладки работы
        # связки в браузере.
 
        add_header X-Nginx-Page-Cache HIT;
 
        # Ищем текущую страницу в мемкэше. Данную строку желательно оставлять без изменений.
        # Если вы используете префикс в настройках Memcache Storage, то перед cache_page добавьте
        # префикс с дефисом. Выглядеть это будет так:
        # set $memcached_key "PREFIX-cache_page-$scheme://$server_name$uri$is_args$args";
 
        set $memcached_key "cache_page-$scheme://$server_name$uri$is_args$args";
 
        # Здесь указываете адрес memcached сервера. Как видите, и здесь можно использовать сокеты.
        # Подробнее про это можно почитать тут http://nginx.org/ru/docs/http/ngx_http_memcached_module.html
        # Очень классной фичей является то, что здесь можно использовать upstream'ы.
        memcached_pass unix:/var/run/memcached/memcached.socket;
 
        # Если кэш не был найден в мемкэше - передаём запрос бэкэнду.
        proxy_intercept_errors on;
        error_page 404 502 = @drupal;
  }
 
  location @drupal {
        add_header X-Nginx-Page-Cache MISS;
        fastcgi_pass unix:/var/run/php5-fpm.sock;
        fastcgi_index  index.php;
        fastcgi_read_timeout 600;
        fastcgi_param  SCRIPT_FILENAME      $document_root/index.php;
        fastcgi_param  QUERY_STRING         q=$uri&$args;
        fastcgi_param  REQUEST_METHOD       $request_method;
        fastcgi_param  CONTENT_TYPE         $content_type;
        fastcgi_param  CONTENT_LENGTH       $content_length;
        fastcgi_param  REDIRECT_STATUS      200;
        fastcgi_param  SCRIPT_NAME          /index.php;
        fastcgi_param  REQUEST_URI          $request_uri;
        fastcgi_param  DOCUMENT_URI         $document_uri;
        fastcgi_param  DOCUMENT_ROOT        $document_root;
        fastcgi_param  SERVER_PROTOCOL      $server_protocol;
        fastcgi_param  GATEWAY_INTERFACE    CGI/1.1;
        fastcgi_param  SERVER_SOFTWARE      nginx/$nginx_version;
        fastcgi_param  REMOTE_ADDR          $remote_addr;
        fastcgi_param  REMOTE_PORT          $remote_port;
        fastcgi_param  SERVER_ADDR          $server_addr;
        fastcgi_param  SERVER_PORT          $server_port;
        fastcgi_param  SERVER_NAME          $server_name;
  }
}

В настройка производительности drupal кэш для анонимов включен
[IMG]http://my.jetscreenshot.com/21512/m_20140512-tnfx-36kb.jpg[/IMG]

Но все страницы идут через бэкенд и более того по какой то причине когда я авторизован страница admin/config погружается минуты 2, если закоментировать строки с поиском страницы в кэше то отрывается нормально (хотя по логике для авторизованного пользователя вообще не должен происходить поиск страницы в кэше)

12.05.2014 14:45
Аватар пользователя DANic
DANic написал:

Сегодня заработало, никаких изменений в настройках nginx и memcashed не делал, возможно ли что не работало из за маленького значения memory_limit в php.ini (было 128 изменил на 256)?

Еще такой момент, есть 2 станицы на которых собирается материал с RSS лент, как сделать так что бы для них кэш сбрасывался при каждом запуске крон (с помощью модуля Cache Expiration такое по видимому не реализовать) или чтобы эти страницы не кэшировались вовсе.

Решил с помощью модуля Rules и добавления правила запуска функции

cache_clear_all('http://itechinvest.ru/aggregator/categories/1', 'cache_page');
cache_clear_all('http://itechinvest.ru/aggregator/categories/3', 'cache_page');

при каждом запуске cron

13.05.2014 18:22
Аватар пользователя tamonten
tamonten написал:

а если у меня не стоит apache, только nginx? как мне изменять настройки

15.05.2014 13:38
Аватар пользователя SoL
SoL написал:

Не могу заставить работать с урл с аргументами по русски. Конкретно:
Есть views с аргументом, передающимся через URL страницы вида site.ru/razdel/аргумент%20идет

В мемкеше вижу, что page cache для таких урлов успешно создаётся, однако nginx их в упор не видит, при попытке загрузить их из мемкеша.

Конфиг в nginx почти 1 в 1 ваш. Гуглил на эту тему, народ пишет мол в nginx переменная $uri с русскими урлами у всех работает корректно...

Куда копать дальше? :)

26.02.2015 14:49
Аватар пользователя Андрей В
Андрей В написал:

Поставили мемкеш. Сайт имеет так же и мобильную тему отдельную (десктопная и мобильная темы переключаются). Проблема в том, что контент некоторых страниц при просмотре с ПК выдается в формате мобильной версии.
Такая же проблема была поначалу и с друпаловским кешированием. Решили путем создания в БД копий кешовых таблиц (с приставкой m_) и в папке мобильного домена (находящейся в корне директории /sites) в settings.php указали эти новые кешовые таблицы.
Теперь вопрос реализовать подобное разграничение в кешировании мемкеша - одно для десктопа и другое для мобайла.
Как быть? Спасибо.

01.11.2015 18:47

Комментировать

                                                                                                               
88 88888888888 88888888ba 88b d88
88 88 88 "8b 888b d888
88 88 88 ,8P 88`8b d8'88
88,dPPYba, 88aaaaa 88aaaaaa8P' 88,dPYba,,adPYba, 88 `8b d8' 88 ,adPPYb,d8 8b d8
88P' "8a 88""""" 88""""88' 88P' "88" "8a 88 `8b d8' 88 a8" `Y88 `8b d8'
88 88 88 88 `8b 88 88 88 88 `8b d8' 88 8b 88 `8b d8'
88 88 88 88 `8b 88 88 88 88 `888' 88 "8a ,d88 `8b,d8'
88 88 88888888888 88 `8b 88 88 88 88 `8' 88 `"YbbdP'88 "8"
88
88
Enter the code depicted in ASCII art style.