Странный случай мистера Time To First Byte

14

У меня есть веб-сервер на Linode 1024 VPS на основе

  • Ubuntu 11.10
  • Nginx 1.0.5
  • PHP 5.3.6 (с PHP-FPM, APC)
  • Лак 3.0.2

И пара блогов, основанных на WordPress 3.3.1. Одним из них является простой блог с конфигурацией по умолчанию, темой и просто постом «Hello World» для тестирования сервера. Другой - это блог, клонированный с другого сервера, с почти 10 тысячами сообщений и более 10 тысячами комментариев. Этот блог имеет около 5 тысяч уникальных вещей в день.

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

Htop показывает также «нормальную» нагрузку при нормальной работе , но необычно большую нагрузку во время ab-теста.

Происходит еще одна странная вещь (самая важная для меня): время до первого байта очень велико , но после этого сайт очень быстро загружается. Это легко проверить с помощью таких сервисов, как tools.pingdom.com, что дает такой результат . Пожалуйста, обратите внимание на эту желтую область, что означает «Время ожидания».

Почему это происходит? Возможные идеи:

  • Плохой конфиг PHP-FPM
  • Время отклика Linode DNS ужасно. Ерунда - тестовый блог разрешает DNS отлично, TTFB - фантастика
  • Плохой конфиг Nginx

Если кому-то нужна дополнительная информация,

javipas
источник
Я думаю, что это может иметь какое-то отношение к if -fдирективе, которую вы используете в locationконтейнере в конфигурации nginx. Исходя из того, что я читаю здесь: wiki.nginx.org/Pitfalls , у меня возникает ощущение, что -fпоиск файла неэффективен, что может вызвать проблему с временем до первого байта, особенно если у вас есть каталоги с большим количеством файлы.
d34dh0r53
1
Несколько соображений: а) в чем отличия от исходного сервера, с которого клонируется блог (например, он запускает тот же стек?) Б) если вы можете, запустить ab непосредственно с сервера, используя localhost и порт. Попробуйте получить доступ через лак, а затем напрямую получить доступ к nginx). c) Включите медленные журналы MySQL и PHP-FPM. d) запустите mysqltuner.pl и посмотрите, сможете ли вы улучшить производительность MySQL (это будет наиболее очевидной разницей между блогами или плагинами). e) Конфигурация PHP-FPM, которую вы разместили, похоже, не используется nginx (/var/run/php5-fpm-tpnet.sock! = /var/run/php5-fpm-www-data.sock)
cyberx86
1
Определенно проблема PHP. Wordpress действительно медленный. Вам понадобится кеширующий плагин, чтобы он получал приличное время загрузки, когда у вас так много контента.
Мартин Фьордвальд,
2
Вы сказали, что «можете запустить ab на localhost и получить 4k req / s» - на какой localhost (предыдущий / текущий) вы ссылаетесь? Если это значение исходит от вашего текущего сервера - сервера с высоким TTFB - тогда ваша проблема стала намного интереснее, поскольку вы фактически устранили PHP, MySQL и ваш веб-сервер. TTFB включает в себя DNS, время прохождения туда-обратно и время обработки. Длинный TTFB обычно происходит из-за обработки (например, PHP / MySQL). Смысл запуска ab непосредственно против nginx состоит в том, чтобы исключить другие компоненты. Кроме того, Varnish, если он настроен правильно, должен обойти бэкэнд, давая очень высокие требования / с.
cyberx86
1
Ваши локальные тесты кажутся недействительными - вы фактически не получили свой блог. Обратите внимание на разницу в размере страницы: 7500 байт при доступе из домена, 151 байт из localhost. Поскольку у вас, вероятно, несколько виртуальных хостов, вам нужно передать заголовок хоста в ab. ab -n 1000 -c 100 -H 'Host: mysite.com' http://127.0.0.1/Тем не менее, разница между кэшированными (Varnish) и некэшированными результатами достаточна для подтверждения позиции, что проблема не связана с сетью, DNS и т. Д. И заключается в обработке, как и ожидалось.
cyberx86

Ответы:

24

Во-первых, это не ответ, а скорее диагностический подход.

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

Время до первого байта

Время до первого байта (TTFB) имеет ряд компонентов:

  • DNS Lookup: найти IP-адрес домена (возможное улучшение: более многочисленные / распределенные / отзывчивые DNS-серверы)
  • Время соединения: откройте сокет к серверу, договоритесь о соединении (типичное значение должно быть около времени «ping» - обычно требуется двусторонняя передача - keepalive должен помочь для последующих запросов)
  • Ожидание: требуется предварительная обработка перед отправкой первого байта (это то, где должно быть ваше улучшение - это будет наиболее важно для динамического контента.

Когда вы смотрите на вывод ApacheBench, вы также видите:

  • Обработка: это сумма ожидания + полной передачи контента (если время передачи значительно превышает ожидаемое время загрузки количества полученных данных, происходит дальнейшая обработка (после получения первого байта) (например, страница сброс содержимого как есть)

Сравнения для устранения компонентов

За некоторыми исключениями, ваша проблема будет заключаться в обработке бэкэнда, которая обычно сводится к слишком сложному / неэффективному коду или плохо настроенному MySQL.

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

  1. Идентичный (клонированный) сайт, работающий на старом сервере и новом сервере:
    • Разница: сервер
    • Результат: старый сервер работает быстро; новый сервер работает медленно
    • Примечания: Здесь вам нужно количественно оценить различия между этими серверами - как с точки зрения используемого стека (Nginx и т. Д.), Так и оборудования (быстрее ли старый сервер, потому что это более мощная машина?)
    • Вывод: код может быстро работать при правильной настройке
  2. Тестовый сайт против полного сайта на новом сервере
    • Разница: контент, темы, плагины и т. Д.
    • Результат: тестовый сайт быстрый, полный сайт медленный
    • Примечания: теоретически этот тест должен помочь вам устранить многие аспекты вашей настройки - DNS, сеть, даже ваши настройки nginx / php / mysql - однако, он не совсем «честный».
    • Вывод: дополнительный контент оказывает существенное влияние на производительность

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

Не изменяя ничего, вы можете сделать несколько других сравнений:

  • Тестирование из удаленного местоположения против локального - это поможет определить, является ли сеть, задержка, DNS и т. Д. Причиной
    • Вы уже (несколько) сделали это и в основном пришли к выводу, что у вас нет проблем с сетью.
  • Тестирование через Varnish (т. Е. Порт 80) по сравнению с nginx напрямую (порт 8080) - старайтесь не менять конфигурацию между тестами - просто используйте правильный порт. Это покажет вам влияние лака. Поскольку Varnish является кэширующим слоем, он должен очень быстро обслуживать все запросы после первого - по сути, он должен обходить серверную часть и обработку, необходимые для создания динамической страницы, и очень быстро обслуживать кэшированную копию.
    • Вы сделали это (хотя и не локально) и продемонстрировали, что Varnish оказывает значительное положительное влияние на вашу производительность.

Настройка вашего бэкенда

К этому моменту вы должны были либо найти проблему, либо сделать вывод, что она лежит в вашем бэкэнде. Это оставляет вас Nginx, PHP или MySQL.

(Я должен упомянуть, что это всегда удобно , чтобы знать , если узким местом является CPU, RAM, или I / O - между sar, top, iostat, vmstat, free., И т.д. , вы должны быть в состоянии прийти к какому - либо выводу по этому вопросу )

Nginx

Nginx просто принимает запросы и либо обслуживает статический контент, либо переводит запросы в PHP-FPM - обычно с Nginx оптимизировать особо нечего.

  • Установить рабочие = # процессорных ядер
  • Включить keepalive (значение 10-15 хорошо)
  • Отключить ненужную регистрацию
  • Увеличьте размеры буфера, если это необходимо
  • Избегайте операторов if (по возможности используйте статические имена вместо регулярных выражений, исключите ненужные расширения)

В идеале у вашего тестового блога и клонированного блога должны быть одинаковые настройки, и в этом случае вы эффективно устранили проблему с Nginx.

заявка

В случае, когда вы пытаетесь идентифицировать проблему в своем коде (например, медленный плагин и т. Д.), Медленные журналы - это место для начала.

  • Включите медленный журнал MySQL и медленный журнал PHP-FPM запустите ваш тест и посмотрите, что будет медленно.

MySQL

  • Увеличьте ваш кэш и запустите mysqltuner.pl, чтобы получить хорошую отправную точку.

PHP

  • отключить ненужные расширения,
  • отключить register_globals, magic_quotes_ *, expose_php, register_argc_argv, always_populate_raw_post_data
  • увеличить предел памяти
  • open_basedir и safe_mode имеют существенное влияние на производительность, но также могут обеспечить дополнительный уровень защиты. Протестируйте с ними и без них, чтобы определить, является ли их влияние на производительность допустимым.

PHP-FPM

  • Отрегулируйте значения pm. * - увеличьте их, чтобы справиться с высокой нагрузкой

Стоит отметить, что ваши результаты htop показывают, что php-fpm потребляет большую часть процессора - и ваша проблема, по-видимому, напрямую связана с этим.

Кэширование

Как только вы оптимизировали каждое возможное узкое место, начинайте кеширование.

  • У вас уже есть кэш opCode (APC) - убедитесь, что он работает (он поставляется с тестовым файлом) - проверьте частоту обращений в кэш и, если возможно, поместите кэш APC в память, а не на диск.
  • Настройте свой код для кэширования (например, с помощью плагина для Wordpress, такого как W3TC)
  • С помощью nginx вы можете настроить кэширование FastCGI, но поскольку у вас есть Varnish, этого лучше избегать.
  • Настройте слой кэширования, такой как Varnish (что вы уже сделали) - и убедитесь, что он работает (например, используйте varnishstat, прочитайте Достижение высокого Hitrate )
  • Добавьте больше кэширования для компонентов вашего сайта - например, MemCached, если применимо

Иногда, учитывая ограничения вашего приложения и аппаратного обеспечения, вы не сможете улучшить производительность бэкэнда настолько сильно - однако в этом и заключается смысл кэширования - чтобы минимизировать использование бэкенда.

дальнейшее чтение

cyberx86
источник
2
Это фантастическое резюме пунктов для анализа. Большое спасибо за комментарий, я постараюсь выполнить тяжелый тест со всеми этими предложениями - некоторые из них, как вы сказали, уже ясны - и посмотрим, смогу ли я наконец обнаружить проблему. С наилучшими пожеланиями, cyberx86.
Хавипас
О том memory_limit, что в другом посте было указано, что это не помогает с производительностью.
forloop