Оптимизация сайта под высокие нагрузки (php,nginx, mysql). Какие критерии доработок? Что необходимо сделать в первую очередь?
Доброго времени суток!
У нас имеется сайт с большой базой пользователей (700 тысяч). Сайт предназначен для записи на мероприятия и одна из его особенностей - БД с кучей полей у некоторых таблиц. Сайт написан на php, использует сервер nginx и СУБД MySQL
С увеличением количества пользователей, готовых участвовать в наших онлайн мероприятиях мы столкнулись с тем, что сайт зависает и жестко тупит, пока есть очередь из запросов пользователей: достаточно 2000-4000 человек, заходящих в течение 20 минут на сайт, чтобы его "положить на лопатки". Пользователи выполняют стандартный набор действий: авторизация, регистрация, запись на мероприятие. Сервер имеет следующую конфигурацию: 24 vCPU intel core ice lake, 128 Gb ОЗУ и SSD хранилище данных. БД, сервер и файлы сайта находятся на одной виртуальной машине, всё это добро размещено на яндекс облаке.
Встал вопрос в оптимизации сайта под высокие нагрузки
Что необходимо сделать в первую очередь в плане оптимизации?
Разработчики данного сайта предложили осуществить следующие работы:
1. Нагрузочные тесты и увеличение ресурсов сервера,
2. Подключение облачной сети быстрой доставки контента (CDN), для оптимизации доставки статического содержимого конечному пользователю и снижении нагрузки на целевой веб-сервер nginx.
3. Развертывание и подключение быстрого кеширующего сервиса REDIS в облачной среде для большей надежности и оптимизации.
4. Вынос MySQL в облачный сервер
Но мы сомневаемся, что этого будет достаточно... какие критерии к оптимизации сайта можно выставить, чтобы проверить выполненные работы и что ещё можно включить в данные работы, если предложения выше подходят для решения?
Дополнительно:
Содержание
> Какие критерии доработок? Что необходимо сделать в первую очередь?
В первую очередь нужно бы выяснить что именно тормозит.
Включите лог медленных запросов.
На каждый сделайте explain, создайте нужные индексы.
Ответы:
Как уже заметили коллеги - первое что нужно выяснить - что тормозит.
Спойлер: 90% что проблема в запросах к бд, так как сам по себе код в большинстве случаев банально отсылает запросы и принимает их результат, выводя его пользователю в несложных действиях. В редких случаях - запросы идут к внешним тормозящим сервисам, например к фейсбуку или другим СС. И крайне редко тормозит сам код, но тут уже опять же - 90% что это некомпетентность разраба, например, не способного построить нормальный запрос и сортирующий данные от бд в коде...
Что конкретно надо делать:
1) Взять за шкирку самого разбирающегося в коде (если таковой существует в проекте), и дать задание описать базовый стек вызовов, если это какой-то самопис, или сразу расставить код замера времени с метками в случае понятной архитектуры. Что то типа такого(класс - древний костыль, но работает, так что матом не ругаться):
Class Timer.php:
|
1 |
class Timer { static $start; static $end; static $marks = []; static $formats = [1=>'']; static function init(){ if(empty(self::$start)) self::$start = microtime(true); } static function setMark($markName = ''){ $time = microtime(true); if($markName == '')$markName = $time; $data['name'] = $markName; $data['time'] = $time; $res['time'] = $time; if(count(self::$marks) > 1)$res['diff'] = $time - self::$marks[count(self::$marks)-2]['time']; else $res['diff'] = 0; $data['diff'] = $res['diff']; self::$marks[] = $data; return $res; } static function timeFormat($number,$format = ''){ if(empty($format)) $format = 3; return number_format ($number,$format,'.',''); } static function report(){ self::$end = microtime(true); self::$marks['start'] = self::$start; self::$marks['end'] = self::$end; self::$marks['all_time'] = self::$end - self::$start; if(!empty(self::$marks)) return self::$marks; } } |
In code:
|
1 |
Timer::init() //some code block 1 Timer::setMark('after block 1'); //some code block 2 Timer::setMark('after block 2'); ... //some code block n Timer::setMark('after block n'); //near end of code Timer::setMark('end'); var_dump(Timer::report()); exit; |
2) Смотрите на блоки жрущие время, делите их до атомарных операций путем деления блоков пополам таймерами.
3) Смотрите что там происходит - оптимизируете*. И так по кругу.
4) Профит.
* Оптимизация
Запросы:
1) Смотреть план запроса (use explain, Luke!).
2) Расставить индексы которых явно не хватает
3) Смотреть не вызывается ли 50 запросов в цикле? Если да - выписать пенделя писавшему, затем переписать в 1 запрос с нормальным джоином.
Код:
Иногда запрос сложно оптимизировать, он вытаскивает много данных, хотя эти данные не часто обновляются. Такие запросы нужно кешировать, для чего используют быстрые ин-мемори хранилища типа редис или мемкеш. В крайнем случае в файлах...
Чаще всего код тормозит на регулярках, хотя "хороший" программист может придумать и более креативные способы погреть процессор.
Что нужно сделать обязательно кроме тестов и как тогда лучше спрашивать с разработчиков, если они предлагают размытые предложения? Хочется понять в какую сторону копать
Бить палкой не вариант? Тогда берите других, эти испортились. Если разработчик не знает как выявить узкие места кода - нахрена он нужен? Код написать сегодня любой чат может... Ну, на крайняк дайте им вышеприведенный вариант решения проблемы...
PS: Кстати, сервер может банально не выдерживать наплыв сетевых соединений, пните адимна, пусть глянет логи.
PPS:
достаточно 2000-4000 человек, заходящих в течение 20 минут на сайт
это равномерные 3-4 рпс, ну или пусть в пике 50 рпс, должно держать даже на несложной конфигурации... Копайте код.
Первым делом необходимо выполнить замеры и найти, что конкретно тормозит. Судя по предложениям разработчиков, подозреваю, что стоит ещё и их уволить.
- Почему ж разработчиков за такие предложения стоит уволить?
- Дмитрий, Ну потому то как минимум вынос мускла с локальной машины в облако увеличит время обработки запросов (с нуля, так как локальная база до сетевых задержек, так как удаленная база).
Хотя нагрузочные тесты конечно не повредят.
- Дмитрий, если предложения переданы именно так, как были озвучены, то они выдают некомпетентность. CDN вообще не при чём, если с сервака не тащат статику гигабитами, что вряд ли. Развернуть Redis и MySQL на отдельных серваках в той же среде - разумное решение, но пункты сформулированы очень странно. Как бы их авторы ещё больше тормозов на сетевых издержках не наловили. Упоминание о том, что у некоторых таблиц куча полей может служить сигналом, что нормализация БД отсутствует, что обычно соседствует с неумением писать оптимальные запросы. Наконец, 2000-4000 человек за 20 минут - это 2-4 запроса в секунду. Если сайт на серваке со 128 гигами памяти и 24-я ядрами ложится от 3 RPS, то руки разработчика кривые чуть более, чем полностью.
- CityCat4, зависит от пинга. он пока не известен.
- Сергей Горностаев, Ну наловят они сетевые задержки без попытки хотя бы пингануть облако сказать нельзя.
Смотря какие запросы и какие требования были к таблицам. Денормализация имеет место быть как решение для высокой нагрузки - другое дело что никогда не слышал что бы от 3 запросов в секунду.Ну и самый главный вопрос - не понятно перед каким количеством разработчиков и с каким бюджетом поставлена задача. Если там 2 человека которыми сказали сделать быстро и дешево - они предложили ровно все возможные решения
- Дмитрий, мы конечно не знаем всех деталей, а потом мои предположения могут быть ошибочными, но в свои фрилансерские времена я интернет-магазины, с очевидно на много более сложной функциональностью, писал в одиночку за пару недель. а они потом легко обрабатывали 300 rps с соразмерными объёмами данных.
- dkis, Прежде всего для ответа необходимо знать детали вашего бизнес-процесса. Если это просто запись на мероприятия, то обеспечить тысячу rps можно без особых ухищрений парой самых дешёвых VPS. Если там какие-нибудь хитрости есть, типа составления оптимального расписания - это уже совсем другая история будет. А дальше профилирование, профилирование и ещё раз профилирование. В зависимости от его результатов оптимизация запросов к БД, оптимизация кода, кэширование, горизонтальное масштабирование и т.д. и т.п. Волшебного рецепта подходящего всегда и всем просто не существует, у каждого проекта собственный путь к высокой эффективности, который лучше прокладывать под руководством человека с опытом в высоких нагрузках.
- Сергей Горностаев, ну как бы весь вопрос в функционале и о том куда летит нагрузка. и каков бюджет и вагон всякого такого. без контекста - говорить что разработчиков на мыло, весьма преждевременно
- dkis, закажите аудит у какой нибудь конторы
- dkis,
точной информации по распределению нагрузки к сожалению нет
Это у вас ее нет, у админа есть лог реквестов к вебсерверу, исходя из которого легко считается рпс.
- dkis, Я извиняюсь, но у вас какой-то шаманский подход к программированию и разработке. "Что надо сделать чтобы сервер заработал по другому, шаманы слушают духов, трясут бубном, но все без толку...". Сегодня весь сегмент программирования ОЧЕНЬ прозрачный, говорю это как человек разрабатывавший код в период когда перл был вершиной эволюции веб разработки, а писали все в редакторе дос навигатора, ну или более продвинутые в фар менеджере... Сегодня можно посмотреть и узнать буквально все, включая какие айпи адреса спамят вас ддосом, а для профайлинга кода придумана куча прибамбасов. Для скюель сервера есть слоулог, если нужно более глубокий анализ - ставим перкону или что-то похожее... Любой нормальный современный движок для веба имеет встроенное логирование, или на крайняк поддерживает установку подходящего модуля... Короче, задача решаемая, все инструменты уже существуют, нужно только время и прямые руки.
Вы делаете какую то хрень без диагностики
Для начала тупо топ в линуксе что в такие моменты жрет больше всего ресурсов и уже это как то пытаться диагностировать и решать
А так вы на уровне у нас ни одного админа и программиста нет мы сделаем какую то хрень по советам интернета
У вас довольно мощный сервер и его должно хватать на порядок больше нагрузки.
CDN не сильно поможет, так как нагрузка на чтение ни о чем, все и так должно работать. Nginx точно не узкое место. Поэтому я бы первым делом включил журналирование медленных запросов в mysql и посмотрел бы что там в топе. А так первый комментарий хороший, поможет найти проблему. Но в целом я бы посоветовал завести метрики и графану, и добавить метрики по операциям в коде и бд. Чтобы иметь представление на будущее. Не знаю насколько сложно это делать в php.
Скорее всего эта проблема связана с БД. Вероятно есть SQL запросы, которые плохо оптимизированы под эту задачу. В этом случае тогда нужно оптимизировать запросы, возможно еще нужно создать индексы, возможно еще произвести тюнинг MySQL, увеличить некоторые буферы и другие настройки.
Для оптимизации нужно:
1. Нужно включить логирование медленных запросов. Много раз использовал эту методику для выявления узких запросов.
После уже можно понять какие php файлы являются проблемными, и их исправить.
Логирование медленных запросов включается так в разделе [mysqld] в файле my.cnf:
|
1 |
slow_query_log = 1 slow_query_log_file = /var/log/mysql/slow.log long_query_time = 1 |
Анализ лог файла делается так:
mysqldumpslow -s c -t 20 slow.log.1 > results.log
2. Также может помочь утилита mysqltuner.pl. Многократно ее использовал для определения проблемных запросов, индексов, которые нужно добавить в таблицы, и других проблем с MySQL/MariaDB.
3. Можно вручную провести анализ запросов при помощи EXPLAIN.
4. Можно сделать замеры выполнения кода, как вручную, через логирование блоков кода, так и через XDebug. И выявить долго выполняющиеся блоки, после этого оптимизировать их.
5. Кроме того нужно посмотреть процессы на сервере, которые занимают много процессорного времени и памяти, это можно сделать через atop или другие подобные утилиты. Можно на основании этого оптимизировать программный код и службы.
6. То что MySQL и сам сервер находятся на виртуальной машине это тормозит работу сервера, виртуальные ноды в любом случае работают медленнее, чем физический сервер. Рекомендую перенести это все на физический сервер с NVMe дисками, с современным процессором и ОЗУ не менее 128 Гб.
Могу помочь настроить логирование, анализ этого и выявить узкие места.
Подозреваю что это банальная очередь запросов, php-fpm как-то настраивался? Nginx в данной цепочке является прокси-сервером, он ожидает ответ от php-fpm.
Думаю необходимо в корне пересматривать структуру проекта.
На каждую сессию сервер резервирует 2 Мб.
То есть на 4000 пользователей это 8 Гб.
И из реальной жизненной ситуации - сервер на 166 Pentium' е, с 256 Мб памяти под FreeBSD и всем "стеком LAMP" обслуживал до 10 запросов в секунду, а здесь с ресурсами на несколько порядков выше 4 запроса в секунду ложат на лопатки.
Первое что можно сделать быстро.
Это индексы, как увидеть тормозящие запросы можно посмотреть тут https://electrictoolbox.com/show-running-queries-mysql/
Далее, оптимизация самой базы. Вот тут есть референсы
https://highload.today/mycnfexample-ram-16/
https://highload.today/index-php-2009-04-23-optima...
https://losst.ru/optimizatsiya-proizvoditelnosti-mysql
https://habr.com/ru/company/oleg-bunin/blog/328458/
И третье: это https://kafka.apache.org/. Строить балансировку для MySQL
В первую очередь смотрим логи nginx. После этого в 80% случаях вам понадобится изменить
- limit.conf
- sysctl.conf
- пулы php-fpm
- и nginx.conf надеюсь тоже у вас не по умолчанию
А после этого, помолясь, смотрим логи Mysql. Если ошибок нет, включаем просмотр медленных запросов.
Часто, но скорей всего не в вашем случае, помогает установка redis. Но redis тоже настраивать нужно уметь и можно сделать просто хуже.
Для решения данной проблемы вы можете воспользоваться услугами фрилансеров. Мы выполним необходимую работу быстро и качественно.
Оставить комментарий Отменить
Ответы
- Есть ответ! к записи Как уменьшить масштаб меньше 100% в Windows 10 (22H2)
- Есть ответ! к записи Аналоги CloudFlare в России?
- Есть ответ! к записи Аналоги CloudFlare в России?
- Есть ответ! к записи Как называется человек, который дизайн придумает для сайта и сверстает его?
- Есть ответ! к записи Можно ли установить Яндекс.Диск на АльтЛинукс?
- Есть ответ! к записи Картинки мутные только на сафари, есть выход?
- Есть ответ! к записи Keenetic. Как настроить SSTP клиент с сертификатом?
- Есть ответ! к записи Чем заменить executor в aiogram 3?
Для оптимизации сайта под высокие нагрузки, необходимо выполнить ряд доработок и настроек как на стороне сервера (nginx, PHP, MySQL), так и на стороне приложения.
1. **Настройка Nginx:**
- Установка и настройка Nginx как веб-сервера.
- Настройка параметров воркеров, соединений, буферов и кэширования.
- Включение gzip-сжатия для уменьшения размера передаваемых данных.
- Настройка кэширования статических файлов, чтобы уменьшить нагрузку на сервер.
2. **Настройка PHP:**
- Установка последней версии PHP и оптимизация его настроек.
- Использование опкод-кэширования (например, OPCache) для ускорения выполнения PHP-скриптов.
- Настройка параметров PHP-FPM для оптимального распределения ресурсов.
- Оптимизация кода приложения: избегание лишних запросов к БД, оптимизация циклов и запросов.
3. **Настройка MySQL:**
- Установка и настройка MySQL для оптимальной производительности.
- Создание индексов на часто используемые поля в таблицах.
- Оптимизация запросов к базе данных, использование правильных инструкций JOIN.
- Масштабирование базы данных: использование кластеризации, шардинга или репликации для улучшения производительности.
4. **Кэширование:**
- Использование кэширования на уровне приложения (например, Memcached или Redis) для хранения часто запрашиваемых данных.
- Кэширование результатов запросов к базе данных для уменьшения нагрузки на сервер.
5. **Мониторинг и отладка:**
- Установка мониторинга производительности сервера (например, New Relic) для отслеживания узких мест и проблем.
- Логирование ошибок и запросов для быстрого выявления проблем и их решения.
При оптимизации сайта под высокие нагрузки необходимо учитывать все вышеперечисленные аспекты, проводить тестирование производительности и постоянно улучшать настройки и код приложения. В первую очередь рекомендуется начать с настройки кэширования, оптимизации базы данных и мониторинга производительности, так как это может дать наибольший эффект в сокращении нагрузки на сервер.