Проблемы производительности сайтов на «1С-Битрикс»
Мы провели сотни аудитов производительности сайтов, и проблемы, которые мы находим в проектах, довольно типичны. В сегодняшней статье мы расскажем не только об этих распространенных проблемах, но еще и об интересных редких ситуациях, с которыми приходилось сталкиваться.
С 2015 года мы оказываем официальную услугу «1С-Битрикс» — аудит производительности сайтов. В рамках аудита мы не просто анализируем настройку и конфигурацию сервера, но также просматриваем код: переносим проект к себе на стенд, где изучаем что именно можно изменить в коде и конфигурации компонентов так, чтобы сайт работал быстрее.
Однако вначале давайте поговорим о том, от чего вообще зависит скорость загрузки страниц и производительность сайта. Существует, на наш взгляд, ошибочное мнение, что все проблемы скорости загрузки сайта можно решить оптимизацией настроек или сменой хостинга. Это действительно помогает в случае нескольких классических ошибок настройки, которые мы рассмотрим ниже, однако, основные проблемы чаще всего кроются в неоптимальных алгоритмах, настройках «1С-Битрикс», проблемах с кэшированием.
Объясняется это довольно просто: современные процессорные технологии достигли пика частоты одного ядра. Что это означает для нас? В условиях, когда один запрос выполняется на одном ядре процессора — нет практически никаких возможностей ускорить время выполнения запроса в два раза. Скорее всего, у процессора на вашем сервере уже высокая частота и со сменой сервера она не станет в два раза выше. Серверы на хостинговых площадках чаще отличаются количеством оперативной памяти и количеством ядер/процессоров, на них расположенных.
Ситуацию можно сравнить со стойкой касс в супермаркете — одна касса может обслужить одного человека за определенное количество времени. Существует предел человеческих возможностей, быстрее которого в заданных условиях покупателя обслужить нельзя. Если в процессе покупки кассиру приходится забивать номер каждого товара в кассу руками, смена кассира может быть и поможет, но в два раза быстрее покупки оформляться не станут. Нужно менять саму процедуру покупки (а в нашем случае — оптимизировать код). Увеличение числа процессоров/ядер на сервере соответственно сравнимо с увеличением количества касс на стойке — одновременно можно обслужить больше покупателей, но каждый покупатель в отдельности будет недоволен.
Таким образом, грамотный анализ производительности проекта включает в себя:
- анализ корректной настройки сервера, аудит серверной конфигурации и мощностей (вдруг все-таки «кассир» очень медленно работает сам по себе — тогда любая процедура будет казаться нам медленной, и мы не сможем понять что же именно оптимизировать);
- алгоритмический анализ проекта, профилирование времени загрузки страниц, анализ работы этих страниц как с кэшированием так и без него (анализ оптимальности процедуры покупки на сайте);
- анализ скорости загрузки сайта в браузере, оптимальности фронтенда.
Рассмотрим эти пункты в подробностях.
Аудит серверной конфигурации
Прежде всего, еще до начала аудита производительности мы проверяем синхронизацию raid-массива (зеркалирование жестких дисков) и его наличие, а также корректность работы системы резервного копирования. Очень часто единожды настроенные зеркалирование и резервное копирование не были после этого проверены ни разу, а между тем, по нашей статистике, резервное копирование ломается раз в месяц. Если вы не проверяли бэкапы больше этого периода — весьма вероятно, что их у вас нет. Следом мы приступаем к аудиту производительности — он состоит из довольно конкретных, но критичных элементов чеклиста.
1. Расположен ли сайт на виртуальном хостинге, VPS/VDS, виртуальной машине?
К сожалению, практически во всех случаях виртуальный хостинг так или иначе продает клиенту больше аппаратных мощностей, чем располагает на самом деле физически. Следствием этого может быть нехватка дисковой подсистемы в пиковые часы, может быть нехватка процессорного времени. Кроме нескольких ситуаций мы рекомендуем использование выделенного сервера на настоящей аппаратной базе для e-commerce проекта, приносящего деньги. Да, разница стоимости между виртуальным и «настоящим» выделенным сервером может составлять десятки раз. Однако эта экономия не стоит того потенциального ущерба (как финансового, так и репутационного), который может быть нанесен в случае аварии на хостинге.
2. Какие версии ПО установлены на сервере?
PHP младше версии 5.5 и MySQL версии младше 5.5 мы рекомендуем к апгрейду. Важно: в случае если проблемы проекта прежде всего связаны с кодом — апгрейд PHP не приведет к ускорению сайта. Но если код оптимален и поддерживает такой переход — использование PHP версии 5.5 и выше может привести к ускорению времени генерации страницы на 20-30%, а использование PHP7 (в случае если проект PHP7-совместим) — к двукратному росту производительности на уровне PHP. Стоит помнить, если ваша страница генерируется за 1000мс, из которых 800мс занимают неоптимальные запросы к БД — даже двукратное ускорение PHP7 приведет к ускорению лишь на 100мс (время ответа станет 900мс вместо 1000мс). Время работы с базой данных от смены версии PHP не изменится.
3. Стоит ли оптимизатор PHP-кода?
В настоящий момент стандартом индустрии и рекомендуемым оптимизатором PHP является opcache. Кроме совершенно уникальных случаев использование opcache является обязательным. Прекомпиляция PHP-кода, которую осуществляет PHP-оптимизатор, ускоряет время обработки PHP-скрипта на 80-90%. Оптимизатор PHP занимается трансляцией PHP-кода в байт-код, который гораздо ближе к машинному. При использовании оптимизатора эта трансляция становится разовой процедурой, а при его отсутствии PHP выполняет трансляцию при каждом пользовательском запросе.
4. Отключен ли отладчик XDebug?
Отладчик XDebug является популярным модулем среди разработчиков, предназначенным для отладки кода. Его удобно и полезно использовать на серверах разработки, но на боевой машине XDebug замедляет время выполнения кода в два раза. Такую ситуацию мы видим довольно часто: XDebug остается запущенным после запуска нового сайта в бой, или же он остается установленным после срочной отладки на боевом сервере. XDebug обязательно надо выключать.
5. Проверка engine таблиц в MySQL
Несмотря на то, что в 2016 году MyISAM считается устаревшим «движком» таблиц, мы встречаем его использование на боевых сайтах. Возможно, причина в переносе таблиц с использованной при разработке базы данных, где тип движка не сильно критичен. Возможно на это просто не обратили внимание, а возможно этот тип таблиц использовали из исторически сложившихся предубеждений. В любом случае для типовых задач следует использовать InnoDB и его производные. MyISAM по своей структуре мало чем отличается от известного всем старого формата dbf-файлов, не предназначенного для промышленного использования в многопользовательской среде. MyISAM часто подвержен блокировкам на уровне таблицы (когда один запрос сайта заблокирует все остальные запросы), очень чувствителен к падениям MySQL (аварийное падение может привести к критической потере данных), с трудом поддается резервному копированию на лету (резервное копирование большой таблицы приведет к блокировке сайта). Всех этих проблем в InnoDB нет, однако, он должен быть корректно настроен.
6. Корректность настройки InnoDB
Прежде всего речь идет о размере buffer pool — внутреннем кэше MySQL. В случае если оперативной памяти достаточно, а размер данных невелик, мы рекомендуем выставить buffer pool выше, чем размер директории с данными (таким образом кэшировав все данные). При аудите хорошо помогают инструменты Percona Tools — в нашем блоге есть обзорная статья. Тема тюнинга MySQL довольно объемная, подробнее о ней поговорим в одной из ближайших статей.
7. Мониторинг работы сервера, проверка использования swap-а
Ни одна оптимизация не поможет, если сервер лежит под огромной нагрузкой из-за наплыва посетителей, или процессам не хватает памяти и часть их выгружена в swap. Swap-файл работает с жесткого диска, который в любом случае в сотни раз медленнее оперативной памяти. Мало того, обычно процессы настолько активно используют оперативную память, что в случае выгрузки ее на диск — дисковая подсистема сервера немедленно достигает своего предела и сайт перестает отвечать. На сервере должен стоять мониторинг: в момент «тормозов» важно понимать, что стало их причиной — сильное использование дисковой подсистемы, нехватка серверного CPU, а может быть вообще исчерпание пропускной способности сетевого интерфейса?
Аудит кода проекта
Убедившись в том, что проблемы сайта не связаны с проблемами хостинга (или решив их), мы переходим к анализу кода. Очень часто может казаться, что в изначально грамотно спланированном проекте проблем с кодом быть не может. По нашему опыту, проблемы возникают не в результате единовременно совершенной ошибки, а из ряда изменений, каждое из которых приводит к небольшому замедлению работы сайта, и суммарно эти проблемы приводят к большой задержке.
Прежде чем заниматься поиском проблемных мест в коде, нужно понимать какие инструменты вы будете использовать для этих поисков, какую информацию они дают и какова у них степень применения.
Для первоначального анализа долгих мест сайта мы используем монитор производительности 1С-Битрикс. Находим самые посещаемые из долго отвечающих страниц — их ускорение приведет к ощутимому снижению нагрузки на сервер. Если не учитывать популярность страницы, а обращать внимание только на скорость ответа, то можно потратить время на оптимизацию страницы, которую запрашивают раз в месяц и которая не создает реальной нагрузки.
Монитор производительности включается следующим образом: в административной панели сайта выбираем в меню «Настройки» -> Панель производительности -> Кнопка «Тестировать производительность». По окончании сбора данных во вкладке «Разработка» будет таблица со всеми посещенными страницами и временем их генерации.
После того как мы выбрали долгие страницы на отдельном сервере (мы знаем мощности этого сервера, и мы знаем, что сервер не загружен) анализируем время создания этих страниц в режиме отладки, смотрим на время генерации отдельных компонентов и понимаем, на что именно следует обратить внимание в анализе кода этих страниц. В первых итерациях мы проверяем как работают страницы в режиме с использованием кэширования, а в последних — изучаем работу сайта без кэша. Нередко страницы, которые открываются довольно быстро с использованием кэша, без него начинают открываться за 30-60 секунд. Казалось бы, ситуация когда кэш истек на редко посещаемых страницах не страшна, однако, пришедший в каталог поисковый бот может серьезно нагрузить сервер, начав обходить такие страницы.
Режим отладки включается непосредственно на странице сайта: в панели администратора необходимо найти пункт «Отладка» и в выпадающем меню выбрать пункт «Суммарная статистика». Если необходимо проверить работу кэша, то дополнительно отметьте галочкой пункт «Детальная статистика кеша».
В некоторых случаях этой информации не хватает — когда некоторые части кода не попадают в режим отладки или когда хочется детальнее изучить структуру вложенности вызовов PHP. В таких случаях мы подключаем модуль профилирования XHProf, который позволяет отследить время выполнения как всего PHP скрипта, так и вложенных функций.
Рассмотрим использование режима отладки и утилиты XHProf на примере страницы каталога с разделами. Проблема: при включенном кэшировании компонент Bitrix:catalog.section медленно исполняется.
Шаг 1. Обращаем внимание, что компонент не кэшируется и выполняется крайне медленно. При этом выполнение запросов занимает приблизительно 16% от времени исполнения компонента. Очевидно, что присутствуют какие-то проблемы в реализации компонента.
Шаг 2. Для отладки PHP используем XHProf. Оборачиваем нужный нам компонент в код утилиты XHProf.
Шаг 3. Обновляем страницу, чтобы XHProf собрал нужные нам данные.
Шаг 4. Открываем страничку с данными XHProf.
Шаг 5. Находим подключение нужного нам компонента Bitrix:catalog.section. Исполнение шаблона компонента Bitrix:catalog.section занимает 1,5 секунды, это большая часть времени генерации всей страницы.
Шаг 6. Идем дальше по стеку вызовов и находим вызов скрипта result_modifier.php. Если пройти дальше, то можно увидеть пользовательскую функцию, в которой исполняются запросы.
Собственно, эта надстройка в виде result_modifier.php является причиной медленной генерации. Таким образом, исправив проблему кода в данной надстройке, можно решить проблему с медленной загрузкой страницы с разделами каталога.
Давайте теперь пройдемся по самым частым проблемам, которые мы встречаем в результате аудита конфигурации 1С-Битрикса.
Аудит конфигурации «1С-Битрикс»
Неправильная структурная организация инфоблоков
Пожалуй, это наиболее распространенная проблема — встречается в 90% проектах. Когда все товары «складывают» в один инфоблок. У такого инфоблока накапливается большое количество свойств всех товаров, это чревато большими выборками и медленным импортом. Рассмотрим на примере абстрактного спортивного магазина, у которого в ассортименте одежда, лыжи, велосипеды (и у каждого вида товаров свои свойства). Свойства товаров попадают в один инфоблок, велосипеды получают свойства лыж и одежды (и, соответственно, наоборот — данные виды товаров получают свойства велосипедов). Представьте, сколько «избыточных» свойств накапливается, если категорий товаров у магазина много.
При этом однажды мы столкнулись с противоположной проблемой: у проекта была правильная структура инфоблоков, но также было много агрегирующих выборок (новинки, акции, хиты). Получилось, что вместо одного запроса в «долгий» инфоблок для генерации выборки отправлялось по запросу в 50+ быстрых инфоблоков и затем ещё происходило их совмещение в коде. Из-за этого компонент в целом стал работать медленнее. Так что если проекту необходима такая функциональность, то надо разрабатывать запасной план — создавать отдельную таблицу в базе данных (делать «денормализацию» структуры инфоблоков), либо через внешнюю агрегацию, либо что-то ещё.
«Самописные компоненты»
Часто встречаются ситуации, когда программисты и веб-студии используют сторонние, «авторские» компоненты, которые при этом не используют имеющиеся возможности платформы 1С-Битрикс. Например, самописные «умные фильтры» не используют фасетные индексы — это значительно увеличивает время исполнения компонента. Случается, что программисты не изучают детально устанавливаемый компонент и упускают из вида ошибки и проблемы, которые он добавляет. Рекомендуем тщательно анализировать устанавливаемые компоненты.
Проблемы с внешними сервисами
Это не связано с самим кодом 1С-Битрикс, но встречается у многих клиентов. Так или иначе многие сайты используют внешние сервисы для дополнительной функциональности на сайте: обновление курса валюты, расчет времени и стоимости доставки товара, API партнеров и т.п. Когда такой внешний сервис начинает долго отвечать — начинает долго отвечать и сам сайт. К сожалению, многие внешние сервисы всегда отвечают долго. Возможное решение проблемы — периодическая загрузка данных по заданию через Cron, и лучше если это будет происходить в наименее загруженное время работы проекта.
Проблемы с фасетными индексами
В большинстве случаев неиспользование фасетного индекса в умном фильтре — это просто недосмотр (если речь не идет о проблеме из предыдущего пункта). Фасетный индекс обязательно необходимо использовать, он значительно ускоряет работу умного фильтра, и, соответственно, снижает нагрузку на процессор и время загрузки страницы. При добавлении новых свойств фасетный индекс надо перестраивать, однако, перестройка его в дневное время (в пиковое время посещаемости) может привести к замкнутому кругу: при отключенном фасетном индексе будет создана фатальная нагрузка на сервер, в результате чего пересоздать фасеты не получится. Единственное правильное решение — перестройка индекса во время минимальной нагрузки.
Ошибки использования API 1С-Битрикс
Выборка свойств в цикле после GetList, когда их можно выбрать в GetList. Сортировка и фильтрация средствами PHP вместо использования arFilter и arSort. В API 1С-Битрикс существует большое число функций, оптимальных для нагрузки на сервер. Разработчику необходимо знать эти функции и уметь их применять. Регулярной ошибкой является, например, получение списка товаров и последующее получение их свойств в цикле, в то время, когда свойства можно получить в основном запросе. Таким образом, например, получив 100 товаров, мы создаем дополнительно 100 запросов к базе данных для получения свойств. Не стоит также выбирать товары для их подсчета — в API 1С-Битрикс есть для этого специальная функциональность. Удивительно, но очень часто мы видим как товары выбираются для того, чтобы посчитать часть из них по какому-то свойству.
Проблемы при генерации меню
В больших проектах становится проблемой генерация меню (либо секций каталога) с подсчетом количества элементов в категориях/секциях. Исходя из этого количества элементов как раз и строятся вышеуказанные области. Для оптимизации скорости работы проекта мы не рекомендуем использовать данную функцию. Подробный кейс был подробно рассмотрен в сообществе разработчиков Битрикс.
Ещё довольно часто наблюдаем проблемы с доработанными меню. К примеру, разработчики не обратили внимание, что меню не кэширует вывод шаблона и написали меню с включением в него самого популярного товара по каждой категории. Получилось, что при просмотре пользователем меню на каждый элемент создаются запросы к базе (что, естественно, замедляет работу проекта). Сам 1С-Битрикс реализует данную «кастомную» функциональность через включение компонентов с такими элементами в result_modifier.php.
Включенный антивирус
Веб-антивирус занимается проверкой страниц сайта на вредоносный контент, который мог быть добавлен в результате взлома/модификации страниц. Хотя эта функциональность и полезна, мы, обычно, рекомендуем отключать этот модуль, оставив включенным модуль проактивной защиты — отключение веб-антивируса может ускорить загрузку страницы на 100-200 мс.
Установленный модуль компрессии
Модуль компрессии предназначен для хостинговых площадок, в которых включить компрессию на уровне веб-сервера не представляется возможным — в основном на «древних» shared-хостингах. В случае, если gzip-компрессию на уровне веб-сервера вы включить можете (а в большинстве случаев это возможно) — мы рекомендуем отключить этот модуль.
Агенты выполняются на хитах
Еще одна историческая функциональность, которая очень часто встречается на проектах клиентов. «Агенты» — регулярно выполняемые задания в 1С-Битрикс, могут выполняться либо через традиционный для нас cron, либо внутри кода, вызванного пользовательским запросом — этот режим называется «Агенты на хитах». В таком режиме 1С-Битрикс каждый запрос пользователя проверяет не пришло ли время выполнить регулярную процедуру (например рассылку), и если время сработало — начинает выполнять эту задачу. Проблема заключается в том, что всё время выполнения задачи пользователь не будет получать результат страницы, а если в настройках веб-сервера установлено ограничение на время выполнения скрипта — такой агент никогда не будет выполнен и почта не уйдет. «Агенты на хитах» созданы для тех площадок, где вы не можете поставить регулярное выполнение агентов на cron, сейчас таких хостинговых площадок осталось очень мало и мы рекомендуем всем отказаться от выполнения агентов на хитах. Подробнее о переключении агентов на крон можно прочитать в статье Николая Рыжонина и в записи Антона Долганина. Кстати, при включении стенда, на котором мы проверяем код проекта, обязательно первым шагом проверяем в MySQL не включены ли агенты на хитах (и не окажется ли так, что в момент когда мы зайдем на сайт, мы выполним какое-либо регулярное задание).
Некорректное использование кэширования
Во многих аудитах мы сталкиваемся с ситуацией, когда кэширование было отключено в отладочных целях и больше не включалось — не забывайте включать. Еще был случай, когда мы в процессе аудита обнаружили, что кэширование некоторых компонентов на странице не работает. Нюанс был в том, что после открытия страницы файл кэша создавался, а на следующее открытие уже инвалидировался. Причиной оказался счетчик просмотра товаров в шаблоне компонента, который при обновлении вносил изменения в инфоблок, что инвалидировало кэш.
С другой стороны, в ряде самописных компонентов мы встречали случаи, когда в кэш загружалась слишком большая выборка данных. Внутри кэша 1С-Битрикс находится сериализованный массив, и если размер одной сущности, лежащей в кэше, становится больше нескольких сотен килобайт (да и этого много), накладные расходы на выгрузку данных из кэша становились сильнее, чем экономия обращения к базе данных.
Проблемы с композитным кэшем
Композитный кэш действительно хорошая и удобная технология, но удивительно как часто ее используют некорректно. Самая простая и очень частая ошибка — сохранение лимита на кэш со значением по умолчанию в 100 мегабайт, это очень мало.
Ещё нередко в результате разработки добавляется новый небольшой компонент, не поддерживающий композит, из-за чего композит со страниц «слетает». Нужно следить за тем, чтобы он сохранялся.
Сам кэш может отдаваться не только из файлов и memcache, но и в виде статических файлов на уровне nginx, однако это используется очень редко. Подробнее про настройку nginx для работы с композитом прочитать на сайте курса разработчиков Bitrix.
Проверка клиентской части
Изображения без оптимизации
Самая частая проблема — использование масштабирования изображений, а также использование несжатых изображений. Всё очень просто, меньше вес картинок — быстрее загрузка. Разработчики об этом прекрасно знают и не грешат такими ошибками, но вот клиенты или контент-менеджеры очень часто загружают огромные, тяжелые изображения. Надо либо подключать автоматические сервисы и модули, либо учить пользователей оптимизировать картинки в ручном режиме.
Проблемы с JS/CSS файлами
Тут регулярно встречаются две проблемы: это подключение JS/CSS файлов нестандартным для Битрикса способом и использование необъединённых JS/CSS файлов. Пост в сообществе разработчиков на эту тему.
Самое важное — неправильное подключение отменяет возможность автоматического объединения JS/CSS файлов, и также отменяет автоматическое обеспечение правильного порядка их подгрузки (сначала CSS файлы, потом JS-файлы).
Несколько раз встречалась проблема с избытком JS — буквально на каждый элемент каталога навешивалось событие отдельным скриптом. При включении опции «переносить JS в конец страницы» возникала мощная нагрузка на сервер.
В этой связи хочется лишний раз напомнить разработчикам про необходимость минификации скриптов, по возможности — асинхронное подключение.
Отдача статики веб-сервером Apache
Как ни удивительно, но до сих пор мы довольно часто встречаем ситуации, когда легковесные статические файлы отдаются не через фронтенд в виде nginx или ему подобный легкий веб-сервер, а через Apache, с которого часто (в особенности при использовании Bitrix Env) раздается динамика. При этом каждый такой запрос создает дополнительное потребление оперативной памяти (Apache значительно тяжелее) и нагрузку на процессор. Мы настоятельно рекомендуем убедиться, что отдачей статики занимается nginx.
Отсутствие компрессии на уровне веб-сервера
Тут все просто — статику надо отдавать с gzip-компрессией, это периодически упускается, к сожалению. Убедиться, что статика отдается с компрессией можно, например, тут.
Подводим итоги
Значимость скорости загрузки сайтов растет: поисковики готовят штрафы в позициях выдачи для медленных сайтов, пользователи наказывают «рублем» и уходят к более шустрым конкурентам. Мы хотим, чтобы хороших и быстрых сайтов было как можно больше. Используйте ресурсы хостинга и платформы 1С-Битрикс грамотно, чтобы получить качественный во всех отношениях проект, который не стыдно разместить в портфолио. Надеемся, наши рекомендации помогут вам в решении проблем производительности проекта. И не забудьте поделиться статьей в соцсетях, если для вас она оказалась полезной.