17 октября 2017

Drupal 8 и Redis, часть 1: прямой доступ NGINX к Redis

Алексей Доронин
Руководитель, разработчик, дизайнер

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

  1. Drupal 8 и Redis, часть 1: прямой доступ NGINX к Redis
  2. Drupal 8 и Redis, часть 2: обзор модуля и настройка NGINX
  3. Drupal 8 и Redis, часть 3: очистка внешнего кеша

Идея, которая стоит за этим решением не новая, её высказывали неоднократно, её суть —  хранить данные в памяти, в быстром key-value хранилище Redis или Memcached и читать их оттуда напрямую из Nginx без обращений к PHP.

Схематично это выглядит так:

Nginx получает запрос страницы и сначала пытается получить данные из Redis, если страницы нет в кеше Redis, запрос передаётся в PHP (в Drupal).

Рассмотрим подробнее как реализовать эту схему.

Nginx

Для того, чтобы NGINX мог взаимодействовать с Redis, нужно подключить модуль HTTP Redis. Как это сделать подробно описывается в статье Компиляция динамических модулей для NGINX (на примере HTTP Redis). Есть более функциональный вариант — Redis2, но нам необходимо только чтение, поэтому обойдёмся более простым модулем HTTP Redis. 

Drupal и Redis

Ставим на сервере Redis и используем его в качестве хранилища кеша Drupal. Это делается с помощью модуля https://www.drupal.org/project/redis

Посмотрим как выглядят записи. В качестве GUI для Redis используем, например, Keylord:

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

render:http

Вот пример полного ключа:

drupal.redis.8.3.7..3f62575ace1138c5777536543445081669d32a76a2a8d6ee514ca459bd0c89f8:render:http://drupalvm.dev/mypage:html

Значение поля Data:

Страница хранится в виде объекта Response в сериализованном виде. Nginx не может прочитать это. 

Redis Page Cache

Будем делать в Redis собственные записи, в которых сохранять html-страницы, эти записи станут доступны для чтения из Nginx.

Redis будет содержать два типа записей:

  1. Стандартный кеш Drupal
  2. Записи, где в качестве значения хранятся html-страницы. Назовём их Redis Page Cache

Для сохранения страниц в собственном кеше (Redis Page Cache), можно использовать, как минимум, два подхода: 

  1. StackMiddleware 
  2. Добавить обработчик на одно из событий, которые срабатывают во время отдачи страницы от Drupal   

Я выбрал второй вариант и событие TERMINATE.

Ссылки по теме:
The HttpKernel Component
The Drupal 8 render pipeline

Итак, у нас получается, что один и тот же Redis используется в двух качествах: в нём хранится стандартный кеш Drupal и Redis выступает в качестве внешнего кеша страниц.

Для Redis Page Cache будем использовать ключи вида: rpcache:url. Пример записи: