Почему ваш сайт на Drupal медленный и что нужно делать, чтобы его ускорить

Ускорение сайта на Drupal

Друпал классная система, которая дает разработчику огромную свободу делать сложные вещи просто.
Хотите материал с кучей полей разного типа (многие из которых имеют по несколько значений) - пожалуйста. Хотите несколько типов контента с разным набором полей - запросто! Хотите легко делать представления и выводить поля из разных материалов, соответствующие различным условиям, да еще и позволить пользователю фильтровать и сортировать материалы по значению этих полей - легко.
При этом нигде даже строчки кода не нужно писать - все "накликивается" из админки.

- Доктор, у меня ничего не болит, я здоров.
- Нет, больной, вы скоро умрете.

Рано или поздно вы начнете замечать, что сайт работает все медленнее. Запросы на фильтрацию контента в модуле views будут занимать все больше времени и периодически выдавать 502 или 504 ошибку, и даже админка начнет тормозить.

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

Немного ускорить сайт на друпале может модуль entity cache, но только если ошибка вызывается на этапе рендеринга представления, а не выполнения запроса к базе.

- А что делать? Давайте перейдем с drupal на django (yii, zend, symphony), наверно он плохой.
- Давайте повторять ошибки на других фреймворках!

Давайте посмотрим на архитектуру вашего проекта.

1. У вас есть материал, который имеет 10 полей. Возможно вы не знаете, но если делать это через fields api (стандартный друпаловский способ), то при этом данные из этого материала располагаются в 11 таблицах + таблицы с данными дополнительных модулей (пути, информация о пользователе и.т.п.)

А теперь представьте, что чтобы загрузить материал придется выполнять sql запрос с как минимум 10 join! Это медленно. Очень.

Знакомая картина?

Если вы посмотрите на поля в своем материале, то с вероятностью 99.9% у вас в одном поле только одно значение, а значит нужно было делать по-другому. Как?

Сущности в drupal - серьезная архитектура.

В drupal правят бал сущности (entity). Может быть вы не знали, но ноды, термины и словари таксономии, пользователи, флаги, комментарии, правила rules, товары и заказы в drupal commerce - это все сущности. Понимаете куда я клоню? Нужно создать свою сущность. Что же такое сущность "на-пальцах".
Это объект, для которого жестко определен набор свойств и способ их хранения в базе данных.
Например, для ноды это nid, uid, title и.т.п. Для пользователя name, mail, uid.

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

А как же множественные поля, картинки, ссылок на термины таксономии и т.п? Расслабьтесь, к сущностям можно добавлять поля, но без фанатизма там, а то получится такой же эффект как и раньше. В общем виде правило: если поле одиночное, его нужно заменить на entity property.

Сортировки, поиск и фильтрация.

- У меня 100000 материалов, я все переделал, создав собственные сущности, и всё равно фильтрация работает медленно. А если я хочу показывать для выбора только те варианты, которые существуют, то вообще все падает. Наверное ваш совет неправильный.
- Совет правильный. Но ваша задача из другой оперы.

Индексированный поиск и фасеты.

Когда на сайте много контента, его обязательно нужно как-то фильтровать, сортировать и осуществлять по нему поиск. Если поиск осуществляется в реальном времени, то при каждом запросе движок базы данных пытается перебрать весь контент, проверить соответствие и вернуть требуемое. После этого, следует еще один запрос на подгрузку из базы недостающих данных для сборки материала и только после этого результат выводится на экран.
Если у вас на сайте много пользователей, то ваш сервер начнет дымиться где-то через 10-20 таких запросов.
Решение - заранее проиндексировать весь контент на сайте. Индексатор обходит контент, анализирует указанные поля, и запоминает в базе где, что лежит и строит специальный индекс, поиск по которому осуществляется в десятки раз быстрее. Когда пользователь захочет выбрать весь контент, содержащий в названии слово Москва, то движок уже заранее будет знать номера материалов, подпадающих под это условие, а значит время и ресурсы будут тратиться только на сборку и отображение результатов поиска.

Кэширование

- Классно, уже быстро. А как ускорить отображение самих материалов?
- Вот тут нужно кэшировать.

Я настоятельно рекомендую использовать view modes для сущностей. Т.е. если мы выводим представление views выводить его не по полям, а rendered entity. Есть замечательный модуль display cache, который может кэшировать все отображение сущности целиком.

- А там же всего 2 вида отображения full и teaser. А мне нужно несколько разных для разных отображений.
- Вы не поверите, но вы можете в своем модуле создать их столько, сколько нужно.

Какие плюсы этого. Предположим у вас есть материал с 10 полями. Вместо того, чтобы делать запрос к 10 таблицам, display cache делает запрос только к таблице кэша. К тому же, вывод не обрабатывается функциями препроцесса и жуками - чистый html.

Кэширование и динамические данные

- Ну вот, включил кэширование и все перестало работать. Загружается быстро, но у всех пользователей одинаковый контент и не работают формы в drupal commerce.
- А вы чего хотели? Это же голый html. Динамический контент в 21 веке грузится с помощью Ajax.

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

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

Более подробно как это сделать с примерами кода показано вот тут: Кэширование и динамические данные в Drupal. Загружаем с помощью AJAX.

Резюмирую:

  • Подход "давайте сделаем сайт с кривой архитектурой, а потом врубим кэш, чтоб все летало" в реальной жизни работает не всегда, а на серьезных проектах не работает никогда.
  • Нагруженный сайт на друпале сделать можно, если делать также, как вы бы делали на любом другом нормальном фреймворке - с придумывания архитектуры.
  • Если уже все плохо, то скорее всего надо будет все переделывать.
- А можно еще быстрее?
- Можно, но об этом в другой раз. У вас пока и от этой скорости голова еще кружится )

Нужна поддержка сайта на Drupal?
Просто напишите нам!