Оптимизация сайта под высокие нагрузки (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 в облачный сервер

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

Дополнительно:

> Какие критерии доработок? Что необходимо сделать в первую очередь?

В первую очередь нужно бы выяснить что именно тормозит.

  • P.S. по опыту, чаще всего проблема в кривом коде (неправильно выбранные алгоритмы, плохо составленные запросы в базу и т.п.) и «заливание проблемы железом» помогает не сильно.
  • CDN делу сильно не поможет (но и не повредит); вынос mysql в облако наоборот замедлит сайт (из-за сетевых задержек) и имеет смысл только если нельзя добавить ресурсов "на месте".
  • Думаю тормозит не статика, а база, так как обычные действия это разного рода работа с ней
  • Сервер большой, а нагругка совскм маленькая. Похоже, проблемы в запросах к БД.
    Включите лог медленных запросов.
    На каждый сделайте explain, создайте нужные индексы.
  • Ответы:

    Как уже заметили коллеги - первое что нужно выяснить - что тормозит.

    Спойлер: 90% что проблема в запросах к бд, так как сам по себе код в большинстве случаев банально отсылает запросы и принимает их результат, выводя его пользователю в несложных действиях. В редких случаях - запросы идут к внешним тормозящим сервисам, например к фейсбуку или другим СС. И крайне редко тормозит сам код, но тут уже опять же - 90% что это некомпетентность разраба, например, не способного построить нормальный запрос и сортирующий данные от бд в коде...

    Что конкретно надо делать:
    1) Взять за шкирку самого разбирающегося в коде (если таковой существует в проекте), и дать задание описать базовый стек вызовов, если это какой-то самопис, или сразу расставить код замера времени с метками в случае понятной архитектуры. Что то типа такого(класс - древний костыль, но работает, так что матом не ругаться):
    Class Timer.php:

    In code:

    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:

    Анализ лог файла делается так:
    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% случаях вам понадобится изменить

    1. limit.conf
    2. sysctl.conf
    3. пулы php-fpm
    4. и nginx.conf надеюсь тоже у вас не по умолчанию

    А после этого, помолясь, смотрим логи Mysql. Если ошибок нет, включаем просмотр медленных запросов.
    Часто, но скорей всего не в вашем случае, помогает установка redis. Но redis тоже настраивать нужно уметь и можно сделать просто хуже.

     

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

     

      • Оптимизация сайта под высокие нагрузки (php,nginx, mysql). Какие критерии доработок? Что необходимо сделать в первую очередь?Есть ответ
      • 08.04.2024
      Ответить

      Для оптимизации сайта под высокие нагрузки, необходимо выполнить ряд доработок и настроек как на стороне сервера (nginx, PHP, MySQL), так и на стороне приложения.

      1. **Настройка Nginx:**
      - Установка и настройка Nginx как веб-сервера.
      - Настройка параметров воркеров, соединений, буферов и кэширования.
      - Включение gzip-сжатия для уменьшения размера передаваемых данных.
      - Настройка кэширования статических файлов, чтобы уменьшить нагрузку на сервер.

      2. **Настройка PHP:**
      - Установка последней версии PHP и оптимизация его настроек.
      - Использование опкод-кэширования (например, OPCache) для ускорения выполнения PHP-скриптов.
      - Настройка параметров PHP-FPM для оптимального распределения ресурсов.
      - Оптимизация кода приложения: избегание лишних запросов к БД, оптимизация циклов и запросов.

      3. **Настройка MySQL:**
      - Установка и настройка MySQL для оптимальной производительности.
      - Создание индексов на часто используемые поля в таблицах.
      - Оптимизация запросов к базе данных, использование правильных инструкций JOIN.
      - Масштабирование базы данных: использование кластеризации, шардинга или репликации для улучшения производительности.

      4. **Кэширование:**
      - Использование кэширования на уровне приложения (например, Memcached или Redis) для хранения часто запрашиваемых данных.
      - Кэширование результатов запросов к базе данных для уменьшения нагрузки на сервер.

      5. **Мониторинг и отладка:**
      - Установка мониторинга производительности сервера (например, New Relic) для отслеживания узких мест и проблем.
      - Логирование ошибок и запросов для быстрого выявления проблем и их решения.

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

    Оставить комментарий