В этой статье мы расскажем об оптимизации магазина на платформе Magento Enterprise Edition. Статья содержит информацию по оптимизации и профилированию работы интернет-магазина на Magento и способах увеличения производительности как при генерации страниц каталога, так и при проведении заказов. Информация будет полезна как техническим специалистам, так и менеджерам, интересующимся производительностью платформы. Проект, который мы оптимизировали - это интернет-магазин детских товаров http://pupsikstudio.com.

Для чего необходима оптимизация?

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

Начальные работы

В начале 2017 года один из наших клиентов на Magento Enterprise одобрил проект по оптимизации его магазина. Прежде всего мы проанализировали работу магазина в New relic - системе для мониторинга производительности приложений. Мы обнаружили большое количество ошибок:

Ошибки возникали каждые 15 минут.

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

В частности:

  • Мы оптимизировали работу модуля для создания лейблов продуктов. Действия, которые выполнялись модулем для одних и тех же товаров несколько раз, были закешированы, что повысило скорость загрузки страниц каталога. 
  • В модуле, управляющим кешем блоков page/html_header, featuredproducts/product_list, catalog/product_bestseller, catalog/product_new наблюдалась проблема, влияющая на производительность - для всех этих блоков время жизни кеша fpc было установлено в 5 сек, и данная настройка применялась для каждого пользователя. Мы исправили время жизни кеша на 86400 и установили деление кеша на группы пользователей. 
  • Модуль бонусной программы грузил всю коллекцию товаров, хотя ему необходим был только один, что замедляло работу магазина на страницах с большим количеством продуктов. Мы устранили эту проблему.


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

  • Включен Flat Catalog Category
  • Включен Flat Catalog Product
  • Включено Объединение CSS/JS файлов
  • Выключен Allow All Products per Page. 

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

Оптимизация корзины и заказов

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

  • Создание специальных индексов, которые были специфичны для программы лояльности и правил корзины. Внедрение таких индексов позволило разгрузить базу данных запросами. 
  • Оптимизация настроек базы данных и PHP. 
  • Мы заменили часть модулей и реализовали аналоги, которые не нагружали базу данных так, как это делали сторонние модули. 
  • Мы внедрили асинхронную индексацию заказов. Поскольку в процессе создания заказа сохранение, а следовательно, и синхронизация данных между указанными таблицами выполнялись несколько раз, наблюдалось сильное замедление процесса создания заказа. Также сторонние модули значительно увеличивали количество сохранений заказа в процессе оформления. Ситуация усугублялась при большом количество пользователей на сайте и одновременном размещении нескольких заказов. 

После примененных правок магазин стал работать быстрее и эффективнее.

Нагрузочное тестирование

После всех изменений мы провели нагрузочное тестирование на staging-сервере, чтобы понимать, каких показателей доступности мы достигли. Для этого мы использовали инструмент для генерации нагрузки Apache Jmeter. Он эмулировал поток клиентов на сайт, трафик был распределен в соответствии с частотностью основных сценариев:

  • открытие случайных категорий / страниц товаров - 95% виртуальных пользователей;
  • вход на сайт / регистрация / оформление заказов - 5% виртуальных пользователей. 

При первом запуске средний RPM составлял 2148. Загружались только статичные страницы (cms, категории, товары) из карты сайта. Было небольшое провисание в середине теста, связанное с тем, что не все страницы были в кеше:

На втором запуске мы добавили к потокам, включающим статичные страницы, сценарии регистрации и оформления заказа. Средний RPM составлял 1602, проблем не было:


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

Результаты на реальных компаниях

На данном этапе мы мониторили магазин в процессе массовой рассылки и отслеживали нагрузку в реальном времени. На подготовительном этапе мы почистили базу данных и логи системы. На реальных компаниях на реальном сервере показатели оказались еще лучше. Магазин стабильно работал при 1300 конкурирующих пользователях и 6000 rpm (запросов в минуту). При этом магазин справлялся со 120 заказами в минуту. Но при таком количестве заказов возникли проблемы с пейментом заказчика - он не справлялся с нагрузкой. В дальнейшем работа пеймента нормализовалась, и кампания прошла успешно.

Решение проблемы с сохранением заказов при высокой нагрузке

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

Это приводило к тому, что новая транзакция не могла получить номер счета, пока не завершилась предыдущая. Мы решили эту проблему, настроив генерацию номера счета заранее, до начала сохранения заказа.

Заключение

Таким образом, мы решали задачу по оптимизации производительности магазина сразу с нескольких сторон:

  • Начальное исследование ядра и архитектуры. 
  • Анализ реальных логов сайта по New Relic и устранение ошибок. 
  • Проведение и анализ результатов нагрузочного тестирования. 
  • Анализ результатов при запуске реальных кампаний. 
  • Исследование и оптимизация сервера. 
  • Оптимизация базы данных.

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

При разработке нового магазина необходимо отслеживать уровень производительности на самых ранних этапах - на уровне анализа отдельных компонентов, и на заключительных фазах, чтобы избежать серьезных проблем в работе сайта.

Надеемся, что наш опыт будет полезен вам!