В данной статье описывается реальная работа по оптимизации скорости обработки запросов веб-сервером, на котором работает сайт интернет-магазина одного из наших клиентов. Коммерчески проект оказался весьма успешным и стал довольно популярным. Со временем сервер перестал справляться с возросшей нагрузкой и в «часы пик» стал заметно тормозить, в результате чего ощутимо снизилась скорость его работы.
Проведённые тесты показали, что среднее время загрузки страниц составило более 350 мс, а иногда посетителям сайта даже не в «пиковое» время приходилось ждать полной загрузки страницы более одной секунды. Дальнейшее игнорирование проблемы становилось невозможным, так как рост посещаемости продолжался, из-за чего время загрузки «медленных» страниц превысило критические 3 секунды, о чём сообщалось в панели Яндекс.Вебмастер в списке критичных ошибок сайта.
Поэтому было принято решение оптимизировать работу сервера так, чтобы уменьшить время обработки входящих запросов и ускорить выдачу данных.
Для повышения скорости обработки и обмена информацией используют кэширование данных: наиболее часто используемые данные перемещают в оперативную память компьютера. Для проектов на Drupal чаще всего используется утилита Memcached, реализующая сервис кэширования данных в оперативной памяти на основе хеш-таблицы. Описанию процесса оптимизации работы веб-сервера и ускорению работы сайта с помощью настройки кэширования данных посвящена данная статья.
Оптимизация работы форм интернет-магазина и кеширование страниц с формами
Одной из ключевых метрик скорости загрузки страниц сайта является время генерации страницы веб-сервером. В работе по оптимизации сайта и сервера для уменьшения времени генерации страниц участвуют наши системные администраторы и специалисты DevOps, разработчики, специалисты со стороны заказчика и хостинг-провайдера. Мы используем профилировку XDebug медленных страниц и анализ времени выполнения отдельных функций PHP для поиска и устранения узких мест в коде сайта.
Для сбора агрегированной статистики времени обработки запроса на загрузку страниц сервером, а также скорости выполнения запросов к MySQL и Solr, с целью последующего анализа, использовался сервис мониторинга NewRelic.
В публикуемой статье описана проблема, довольно распространённая для сайтов на Drupal, и показано решение, позволяющее на 32% уменьшить время обработки запросов на загрузку страниц интернет-магазина.
Проблема
Есть в Drupal 7 давняя особенность — форма автоматически кэшируется при использовании AJAX фреймворка . При каждом выводе такой формы в таблице cache_form создаётся две записи — одна для структуры формы и одна для её состояния. Кэширование необходимо для корректной работы AJAX обработчика, которому нужно знать структуру и последнее состояние формы.
В случае, когда таких форм на странице много, возникает проблема быстрого роста количества записей в таблице cache_form . Например, «Добавить в корзину» в Commerce: запрос на вывод 50 товаров приведёт к созданию 100 записей в таблице cache_form при каждом просмотре страницы каталога. На сайте с высокой нагрузкой это приводит к тому, что таблица cache_form может иметь размер в несколько десятков гигабайт.
Учитывая тот факт, что кэш форм в Drupal 7 тесно связан с кэшированием страниц с минимальным временем жизни памяти (задаётся на странице «Производительность» ), если удалить кэш формы раньше, чем память страницы, возникнет ошибка «Некорректные POST-данные формы» при взаимодействии с формой. Если задать минимальное время жизни памяти, устаревший кэш форм не будет очищаться в течение установленного времени.
Для исправления этой проблемы уже существует несколько решений:
- Переменная form_cache_expiration . Данная переменная была добавлена в версии 7.61 и позволяет управлять временем хранения кэша форм, которое по умолчанию равно 6 часам. Основной недостаток заключается в сильной зависимости от механизма очистки устаревшей памяти, без своевременного вмешательства которого, размер cache_form будет продолжать расти.
- Модуль OptimizeDB . Позволяет гибко настроить очистку таблицы cache_form по cron. Можно задать полную очистку таблицы или очистку только устаревших записей. Но тогда высока вероятность возникновения ошибки «Некорректные POST-данные формы», при этом размер таблицы cache_form всё равно останется слишком большим.
- Модуль Safe cache_form Clear предоставляет Drush команду для очистки устаревших записей в таблице cache_form . Недостатки аналогичны недостаткам модуля OptimizeDB .
- Модуль Commerce Fast Ajax Add to Cart . Решение от xandeadx , направленное на корень проблемы — кэширование стандартной формы Drupal Commerce добавления товара в корзину. Минус решения, как ни странно, в том, что AJAX фреймворк не используется, а для нашего проекта разработчиками уже был написан нестандартный диалог добавления в корзину с использованием AJAX-команд Drupal. Кроме того, это решение не универсально и работает только для формы добавления товара в корзину;
Решение
Для примера возьмём чистую установку Drupal 7.67 с модулем Commerce 1.15. Реализуем страницы каталога с помощью Views. На каждой странице выведем по 50 товаров, в каждом тизере товара выведем кнопку добавления в корзину. Для удобства генерируем товары с помощью модуля Commerce Devel . Для AJAX-ификации кнопки добавления товара в корзину используем модуль Commerce Ajax Add to Cart . Открываем страницу каталога и проверяем — в таблице cache_form появилось 100 новых записей, проблема воспроизведена.
Решение, предлагаемое в данной статье, частично основано на данном комментарии . Для его реализации потребуется создать небольшой кастомный модуль или добавить код в уже имеющийся. В нашем примере это будет модуль custom .
Первым делом определим путь для нового AJAX-обработчика формы. По своей структуре он похож на определение пути «system/ajax» в модуле system .
/**
* Implements hook_menu().
*/
function custom_menu() {
$items['custom/form/ajax'] = array(
'title' => 'AJAX callback',
'page callback' => 'custom_form_ajax_callback',
'delivery callback' => 'ajax_deliver',
'access arguments' => array('access content'),
'theme callback' => 'ajax_base_page_theme',
'type' => MENU_CALLBACK,
);
return $items;
}
Изменим путь AJAX-обработчика у кнопки добавления товара в корзину (свойство path ). Здесь важно не путать свойства path и callback — первое определяет адрес, на который будет отправлен AJAX-запрос, а второе указывает функцию, которая при этом запросе будет вызвана для формирования ответа. Как правило, path не указывают и берётся значение по умолчанию «system/ajax» , его и требуется поменять. Также принудительно отключим кэширование, интересующей нас, формы.
/**
* Implements hook_form_alter().
*/
function custom_form_alter(&$form, &$form_state, $form_id) {
if (strpos($form_id, 'commerce_cart_add_to_cart_form') !== FALSE) {
// Указываем, что хотим самостоятельно обработать AJAX-запрос к форме.
$form['submit']['#ajax']['path'] = 'custom/form/ajax';
// Отключаем кэширование формы.
$form_state['no_cache'] = TRUE;
}
}
Наконец, реализуем функцию custom_form_ajax_callback() , которую ранее указали в определении пути «custom/form/ajax» . Код функции частично повторяет код функций ajax_get_form() и ajax_form_callback() . Основная идея заключается в том, что нужно получить правильное состояние формы без использования кэша, так как мы его уже отключили. Важно отметить, что приведённый далее код универсален и может быть применен для отключения кэширования других AJAX-форм, за исключением блока, в котором выполняется формирование товарной позиции. Именно в данном блоке происходит построение состояния формы, необходимой для корректной валидации и сабмита. Для поддержки атрибутов товаров потребуется доработка этого кода. Для других форм потребуется написать аналогичный код.
/**
* Menu callback; handles Ajax requests for forms without caching.
*
* @return array|null
* Array of ajax commands or NULL on failure.
*/
function custom_form_ajax_callback() {
// Проверяем, что обрабатываем AJAX-запрос к форме.
if (isset($_POST['form_id']) && isset($_POST['form_build_id'])) {
$form_build_id = $_POST['form_build_id'];
$form_id = $_POST['form_id'];
$commands = array();
// Инициализируем состояние формы.
$form_state = form_state_defaults();
$form_state['build_info']['args'] = array();
// Заполняем состояние формы. Данный код уникален в рамках обрабатываемой формы.
// Проверяем, что форма является формой добавления товара в корзину.
if (strpos($form_id, 'commerce_cart_add_to_cart_form_') === 0) {
$product = commerce_product_load($_POST['product_id']);
if (!empty($product)) {
// Формируем сущность товарной позиции на основе данных отправленной формы.
$line_item = commerce_product_line_item_new($product, $_POST['quantity'] ?? 1);
$line_item->data['context']['product_ids'] = array($product->product_id);
$line_item->data['context']['add_to_cart_combine'] = TRUE;
// Добавляем товарную позицию в состояние формы.
$form_state['build_info']['args'] = array($line_item);
}
}
Результаты
В нашем примере добавление вышеуказанного кода приводит к сохранению AJAX-функционала кнопки добавления товара в корзину при отключённом кэшировании формы. Обновление страницы каталога теперь не приводит к созданию 100 записей в таблице cache_form. Результат обработки AJAX-запроса аналогичен результату обработки при использовании кэша. Изменения формы, добавленные в рамках Drupal API (например, атрибуты товаров) либо потребуют небольших изменений в коде (построения состояния формы), либо не потребуют их вообще.
Кроме того, интересен результат применения решения на реальном проекте, для которого оно и было реализовано:
- Количество SELECT запросов к таблице cache_form уменьшилось в 10 раз;
- Количество INSERT запросов к таблице cache_form уменьшилось в 10 раз;
- Среднее время обработки запроса сервером уменьшилось на 32% (с 352 до 241 миллисекунд).
Более подробно статистика отображена на скриншотах.
Среднее время от запроса до ответа сервера APP SERVER уменьшилось с 352 до 241 миллисекунд. Размер таблицы cache_form уменьшился с ~10Гб до 200Мб.
Таким образом получилось сократить время транзакции на 32%. Дальнейшие доработки других форм сайта аналогичным образом позволят улучшить эти показатели.
Тонкая настройка кэширования страниц в Memcached и мониторинг кеша страниц
Одним из самых важных факторов, влияющих на отказы и конверсии интернет-магазина, да и любого сайта, является скорость загрузки страниц.
Слишком медленная работа сайта способна свести на нет любые старания владельца по повышению конверсии веб-проекта. Причина слишком медленной загрузки веб-страниц очень часто содержится в медленной обработке запросов и низкой скорости процессов обмена данными на самом веб-сервере.
Как известно, самыми медленными в компьютере являются операции ввода и вывода данных, хранящихся на жёстком диске. Даже самые быстрые современные устройства хранения зачастую не могут обеспечить требуемую скорость чтения и записи данных через интерфейс жёсткого диска. Чтобы ускорить процессы обмена и обработки информации применяется кэширование — т.е. хранение часто используемых данных в оперативной памяти, для чего в проектах на Drupal чаще всего используется утилита Memcached, настройке которой и посвящен данный раздел статьи.
Проблема
Работая над задачей по увеличению скорости загрузки страниц сайта интернет-магазина, мы обнаружили неожиданное поведение сервиса кэширования. Несмотря на то, что утилита кэширования данных Memcached была настроена и запущена, страницы отдавались по запросу не из памяти, как ожидалось, а генерировались всякий раз заново, загружая данные с жёсткого диска даже при повторном запросе от пользователя.
Погрузившись в проблему, мы поняли, что невозможно определить объем памяти, используемый именно под хранение страниц в кэше, ведь кэш Drupal хранит не только их. Было принято решение тщательно исследовать работу Memcached и перенастроить его так, чтобы страницы выдавались из памяти сайта.
Анализ
Для того, чтобы понять масштаб проблемы и оценить потенциальную эффективность ее решения мы использовали следующие инструменты:
- memcached-tool — perl-скрипт, входящий в стандартную поставку Memcached. Позволяет просматривать статистику запущенного процесса Memcached. Его удобно использовать в bash скриптах для организации автоматического мониторинга.
- PHPMemcachedAdmin — панель управления для отображения статистики и работы Memcached, с помощью которой удобно осуществлять мониторинг работы Memcached.
- логи WEB сервера. Мы включили в действующий формат логов nginx логирование заголовков кэша Drupal. Для этого в директиве log_format добавили еще одну переменную $sent_http_x_drupal_cache .
- Zabbix-сервер — центральный узел мониторинга.
Далее рассмотрим подробнее, как работает Memcached и как мы использовали, перечисленные выше, инструменты.
Администраторы сайтов и веб-серверов зачастую просто устанавливают Memcached, выделяя ему, например, 1-2 Гб оперативной памяти, и благополучно забывают про него, не заморачиваясь долгой и трудоёмкой настройкой, полагая, что он прекрасно работает и без этого. Но так ли это на самом деле? С помощью панели PHPMemcachedAdmin можно детально изучить работу службы. Вот пример главного экрана мониторинга:
Первое, что обращает на себя внимание — используемая память. Если вы используете 100% выделенной памяти, значит новые запросы не будут кэшироваться, так как под них не остаётся ресурсов.
Второй важный параметр — wasted. Если процент wasted высокий, значит используемая память расходуется не рационально. Чтобы понять, что такое wasted, нужно разобраться, как Memcached использует выделенную ему память.
Вся выделяемая память в Memcached делится на слабы (Slab). Слаб, в свою очередь, содержит чанки (chank), а в чанках уже хранятся непосредственно данные. Каждый слаб хранит в себе чанки одинакового размера. Такой подход к хранению данных позволяет Memcached легко и быстро находить область в памяти для записи новых данных.
Когда в Memcached приходят данные для записи, он находит слаб, который содержит чанки размером, максимально приближенном к размеру поступивших данных, и записывает эти данные в него, при условии, что он свободен. Более в этот чанк ничего записать нельзя. Если размер чанка превышает размер записанных в него данных, в чанке остается немного свободной памяти, которую уже нельзя использовать. Суммарный объем этой неиспользуемой памяти и составляет wasted.
Таким образом, только посмотрев на главный экран панели PHPMemcachedAdmin, можно сразу определить, насколько рационально используется память в Memcached и нужно ли вообще что-то менять. Но если используемая память расходуется на 100%, а процент Wasted относительно невысок, то достаточно увеличить выделяемую для Memcached память. Если же процент Wasted высокий необходимо оптимизировать работу Memcached. Хорошим показателем работы является 15-25% Wasted и 20-25% свободной памяти. Это означает, что ваш экземпляр Memcached рационально использует выделенную ему память и у него есть небольшой запас для записи новых запросов.
Решение
В зависимости от того, что хранится в кэше, а точнее — от объема данных, Memcached по-разному настраивается. Поэтому первое, что мы сделали — отделили кэш страниц от всего остального, т.к. размер страницы сильно отличается от остального кэша, который хранится в памяти.
Для этого на сервере клиента мы развернули второй инстанис Memcached. Сделать это было не сложно — мы скопировали существующий юнит systemd и вписали в него новый путь к конфигурационному файлу.
cat /etc/systemd/system/memcached1.service
[Unit]
Description=memcached daemon
After=network.target
Documentation=man:memcached(1)
[Service]
ExecStart=/usr/share/memcached/scripts/systemd-memcached-wrapper /etc/memcached1.conf
[Install]
WantedBy=multi-user.target
Затем скопировали файл /etc/memcached.conf в /etc/memcached1.conf и указали в нем новый файл сокета.
systemctl daemon-reload
systemctl start memcached1 && systemctl enable memcached1
Готово. Теперь у нас есть два экземпляра Memcached (memcached и memcached1), с которыми «научим» работать Drupal. Мы используем модуль Memcached Storage . Для его настройки изменим блок описания кэша в файле settings.php :
$conf['cache_backends'][] = 'sites/all/modules/memcache_storage/memcache_storage.inc';
$conf['cache_default_class'] = 'MemcacheStorage';
$conf['cache_class_cache_update'] = 'DrupalDatabaseCache';
$conf['cache_class_cache_form'] = 'DrupalDatabaseCache';
# Configure Memcache Storage module.
$conf['memcache_storage_wildcard_invalidate'] = 60 * 60 * 24;
# Set current extension.
$conf['memcache_extension'] = 'Memcached';
# Configure memcached extenstion.
$conf['memcache_options'] = array(
Memcached::OPT_TCP_NODELAY => TRUE,
Memcached::OPT_BUFFER_WRITES => TRUE,
Memcached::OPT_NO_BLOCK => TRUE
);
$conf['memcache_servers'] = array(
'unix:///tmp/memcached.sock' => 'default',
'unix:///tmp/memcached1.sock' => 'page',
);
$conf['memcache_bins'] = array(
'cache' => 'default',
'cache_page' => 'page',
);
# Set custom expiration for cached pages.
$conf['memcache_storage_page_cache_custom_expiration'] = TRUE;
$conf['memcache_storage_page_cache_expire'] = 60 * 60 * 24;
$conf['memcache_storage_key_prefix'] = 'XXXXXXXXXXXX';
$conf['page_compression'] = 1;
$conf['page_cache_maximum_age'] = 60 * 60 * 24;
Отлично! Теперь страницы попадают в кэш, созданный memcached1, а все остальное — в сформированный memcached. Теперь осталось оптимизировать работу обоих экземпляров memcached. При этом следует помнить, что у каждого — свой конфигурационный файл.
Наверняка вы столкнетесь с высоким процентом Wasted. Рассмотрим методику его уменьшения.
У нас есть возможность регулировать размеры чанка. В параметрах Memcached мы выставляем размер начального чанка, т.е. размер чанка, который создается в первом слабе. И выставляем так называемый фактор роста — это соотношение размера большего чанка к меньшему. Т.е. если размер начального чанка составляет 1 кб, а фактор роста — 1.15, то его размер во втором слабе составит 1 кб х 1.15 = 1.15 кб, размер чанка в следующем слабе 1.15 кб х 1.15 = 1,3225 кб и так далее.
Подбор подходящих значений начального чанка и фактора роста является занятием довольно кропотливым. Выставляя сначала одни значения, которые кажутся вам подходящими, через какое-то время следует проверять полученный результат и при необходимости корректировать параметры, выставляя новые значения. У нас ушло около недели, чтобы выбрать оптимальные параметры для интернет-магазина нашего клиента.
Для этого можно воспользоваться тем же PHPMemcachedAdmin. Перейдя по ссылке See this Server Slabs Stats в панели управления, вы увидите текущие состояния слабов, процент Wasted в каждом слабе, количество и размеры используемых чанков, которые хранятся в каждом слабе.
Учтите, что максимальное количество слабов — 63. Поэтому не стоит выставлять слишком маленький фактор роста, это может привести к тому, что у вас будет много слабов с маленьким размером чанков, а под данные большего размера у вас не останется слабов. Для настройки параметров Memcached используются следующие ключи: -m — задает количество оперативной памяти для Memcached, -n — определяет размер начального чанка в байтах, -f — назначает фактор роста. Вот небольшой пример настройки Memcached:
cat memcached1.conf
-m 1536M
-u www-data
-s /tmp/memcached1.sock
-a 0777
-n 40960
-f 1.015
После оптимизации настроек Memcached не стоит думать, что об этом можно забыть. Приложение развивается, объем данных, поступающих на хранение в Memcached может измениться. Мы рекомендуем время от времени проверять состояние Memcached и при необходимости корректировать параметры.
Мы оптимизировали работу Memcached и надеемся, что страницы будут всегда отдаваться из кэша. Чтобы убедиться, что все работает так как должно быть, можно воспользоваться тем же PHPMemcachedAdmin. На главной панели есть секция Hit & Miss Rate с гистограммой, отображающей количество попаданий в кэш. Удобная визуализация, но гораздо полезнее эти данные хранить в системе мониторинга, чтобы отслеживать работу кэша во времени и среагировать в случае изменения работы приложения. Чтобы получить те же данные, можно воспользоваться консольной утилитой netcat (nc), например, так:
echo "stats" | nc -U /tmp/memcached.sock -w 1 | grep get_hit | awk '{print $3}'
4330
echo "stats" | nc -U /tmp/memcached.sock -w 1 | grep get_miss | awk '{print $3}'
41
Такие несложные ванлайнеры можно запускать с помощью zabbix-агента и хранить результаты на zabbix-сервере.
Тюнинг производительности базы данных MySQL
На производительность сайта существенно влияет скорость работы СУБД MySQL. Для оптимизации работы MySQL мы используем разработанный нами сервис MySQLConfigurer: https://habr.com/ru/post/499410/
Он позволяет ускорить работу MySQL на 30% по сравнению с параметрами MySQL по умолчанию: https://docs.google.com/spreadsheets/d/1J9FDgBGbvNA356d74WKYBaEzSwK7H-wgjHEQgYh8CMI/edit?usp=sharing
При заходе на закэшированную страницу Drupal делает не более двух запросов к БД. Однако при заходе на незакэшированную страницу или при заходе на сайт авторизованным пользователем количество запросов может быть велико. Нами была проведена оптимизация кэширования на уровне блоков и оптимизация кэша сущностей Drupal в memcached таким образом, чтобы при загрузке страницы карточки товара интернет-магазина не из кэша делалось не более 300 запросов к БД.
Прогрев и мониторинг кэша страниц
Картина, полученная в мониторинге, может вам не понравиться, т.к. количество не попаданий в кэш (miss) может быть довольно велико. Причина в методе работы Memcached. Чтобы страница попала в кэш, ее должен кто-то запросить. Очевидно, что главная страница сайта или страницы с популярными товарами быстро попадут в кэш. Но представьте себе, что посетитель интернет-магазина ищет товар не из самой популярной категории. Он будет переходить от страницы к странице, которые генерируются не из кэша, скорость работы сайта конкретно для этого человека окажется слишком низкой, что может оттолкнуть потенциального покупателя. Чтобы максимально увеличить количество попаданий страниц в кэш наша команда реализовала так называемый «прогрев кэша». Он представляет собой текстовый файл со списком url-адресов страниц, которые нужно добавить в кэш, и bash-скрипт, который с помощью утилиты curl обращается к каждой строке, содержащей url-ссылку из этого файла.
Чтобы реализовать этот инструмент, был написан следующий bash-сценарий:
#!/bin/bash
# файл со списком url
$SOURCEFILE="urls.txt"
# функция, которая запрашивает страницу
function cached_url() {
time=$(date +"%T")
curl -LI -w "$time;%{time_total};$1\n" -o /dev/null -s $1
}
# запускаем перебор файла и вызываем функцию cached_url для каждого url
flag=0
cat $SOURCEFILE | while read url; do
cached_url $url &
let "flag = flag + 1"
if [[ $flag == "4" ]];
then
# мы делаем периодические паузы, чтобы сильно не нагружать сервер
wait
sleep 1
flag=0
fi
done
Нужно поместить этот скрипт в крон, который нужно запускать каждую ночь после импорта и обновления данных сайта, чтобы обеспечить попадание страниц сайта в кэш еще до того как к ним обратится первый реальный посетитель. При этом необходимо учитывать, что выполняться такой скрипт может достаточно долго, генерируя довольно чувствительную нагрузку на сервер. Поэтому необходимо продумать время его запуска и количество загружаемых url-адресов. В нашем случае мы добавляли только те страницы, которые были либо слишком объёмными, либо слишком редкими для загрузки пользователями.
Еще одним инструментом мониторинга правильной работы кэша являются логи Web-сервера. Дело в том, что Drupal к каждой странице добавляет http заголовок под названием x-drupal-cache, который может иметь только два значения — HIT или MISS. Мы добавили в формат лога nginx переменную $sent_http_x_drupal_cache , чтобы отслеживать эти заголовки и точно понимать, какой запрос был отдан из кэша и была возможность анализировать общую картину.
Мы храним логи nginx в Elasticsearch. Kibana — фронтенд для визуализации логов в Elasticsearch, предоставляет отличные возможности для визуализации, сортировки, выборки и анализа логов. Немного поработав с дашбордами можно получить исчерпывающие графики и гистограммы попадания запросов в кэш.
Другой возможностью Kibana является поиск и сортировка логов. Например, вы можете найти все MISS запросы и отсортировать их по количеству вхождений в лог за день или неделю, т.е. составить своеобразный ТОП не кэшируемых запросов — первых претендентов на добавление в прогрев кэша.
Результаты
Оптимизация кэширования AJAX-форм позволила нам ускорить обработку запросов на 32%. Благодаря тонкой настройке Memcached и использованию прогрева кэша мы смогли добиться того, что все входные страницы сайта хранятся в оперативной памяти. Проведённые тесты показали среднее время загрузки страниц 48 ms — это пятикратное ускорение! Но для выполнения других операций очень важна общая производительность сервера.
Добившись ускорения работы сайта с помощью оптимизации кода, работы баз данных и прочего сопутствующего ПО, наблюдая за процессом роста числа посетителей и загрузок страниц сайта интернет-магазина, мы подумали, что можем столкнуться с проблемами недостаточной производительности сервера во время пиковых нагрузок. Кроме того, запас производительности сервера будет очень кстати в случае добавления в интернет-магазин новых функций или, например, для добавления новых веб-проектов, расширяющих коммерческие возможности клиента. Поэтому предложили клиенту перевести сайт на более мощное и производительное аппаратное обеспечение.
Перед началом работ наш клиент арендовал виртуальную машину с 4 ядрами cpu 3200 Mhz и 16 Gb оперативной памяти. После анализа работы интернет магазина было принято решение о переносе сайта на выделенный физический сервер со следующей конфигурацией: процессором Intel® Xeon® E-2236 CPU @ 3.40GHz 12 core и 32 Gb оперативной памяти.
Среднее время кэшируемых страниц сайта сократилось до 11.9 ms, а не кэшируемых — снизилось в среднем на 76 %, с 616 мс до 102 мс.
В итоге мы получили следующие результаты мониторинга скорости загрузки страниц сервисом Newrelic:
До начала работ
После окончания работ и перехода на «новый» сервер
Заключение
Разрабатывая веб-проект, необходимо очень внимательно отнестись к качеству кода и стилю программирования. Ошибки, допускаемые при программировании, накапливаются, что весьма негативно сказывается на скорости загрузки страниц у пользователя. А неаккуратный и запутанный стиль программирования не способствует быстрому поиску и устранению этих ошибок.
Кэширование в оперативной памяти сервера страниц сайта, особенно крупного интернет-магазина, заметно повышает скорость обработки запросов и загрузки страниц у пользователя. Но использование программы, обеспечивающей сервис кэширования данных, требует тщательной настройки и хорошего понимания самого процесса. В противном случае это не даст никакого эффекта и окажется совершенно бесполезным, а обработка запросов и выдача результатов пользователю так и будет происходить через жёсткие диски.
Разумеется, требуется тщательный подход к выбору аппаратной конфигурации сервера, на котором базируется веб-хост. Использование более мощного аппаратного обеспечения позволяет быстрее обрабатывать запросы пользователя, имея при этом хороший запас прочности при возникновении пиковых нагрузок, а также резервы для модернизации коммерческого веб-проекта.
Высокая скорость обработки запросов и быстрая загрузка страниц в браузерах пользователя делает пребывание посетителя на сайте наиболее комфортным, увеличивает вероятность совершения сделки, а значит повышает коммерческую эффективность сайта в целом.