Назад | Перейти на главную страницу

Как устранить проблемы производительности PHP, MySQL и универсального ввода-вывода

У меня есть веб-сайт на базе WordPress, работающий на виртуальном хостинге. Его время отклика очень приличное (около 2 с для получения HTML-страницы и 5 с для загрузки всех ресурсов).

Я планировал перенести его на выделенный виртуальный сервер (Ubuntu 12.04 LTS), что теоретически должно улучшить ситуацию и сделать их более согласованными, учитывая, что он не используется совместно. Однако я наблюдал серьезное снижение производительности, когда для создания страницы требовалось 10 секунд.

Я исключил проблемы с сетью, отредактировав /etc/hosts на сервере и сопоставление домена с 127.0.0.1. Я использовал тестер нагрузки Apache ab чтобы получить HTML, чтобы исключить JS, CSS и изображения. Все равно прошло 10 секунд.

У меня Zpanel установлен на сервере, который также использует MySQL, и его страницы появляются довольно быстро (1,5 с), а также phpMyAdmin. Выполнение некоторых запросов к базе данных wordpress напрямую через phpMyAdmin также возвращает их довольно быстро, со временем запроса в диапазоне от 10 до 30 миллисекунд.

Памяти также достаточно: из доступных 1 ГБ физической памяти используется только 800 МБ, так что это тоже не проблема подкачки. Я также установил APC, чтобы попытаться улучшить производительность PHP, но это не помогло.

Что еще мне следует искать? Что могло вызвать такое снижение производительности? Может быть, это какая-то проблема ввода-вывода, поскольку я работаю на виртуальном сервере в облаке?

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

ОБНОВИТЬ с участием sar вывод (каждую секунду), когда я выполнял HTTP-запрос:

02:31:29        CPU     %user     %nice   %system   %iowait    %steal     %idle
02:31:30        all      0.00      0.00      0.00      0.00      0.00    100.00
02:31:31        all      2.22      0.00      2.22      0.00      0.00     95.56
02:31:32        all     41.67      0.00      6.25      0.00      2.08     50.00
02:31:33        all     86.36      0.00     13.64      0.00      0.00      0.00
02:31:34        all     75.00      0.00     25.00      0.00      0.00      0.00
02:31:35        all     93.18      0.00      6.82      0.00      0.00      0.00
02:31:36        all     90.70      0.00      9.30      0.00      0.00      0.00
02:31:37        all     71.05      0.00      0.00      0.00      0.00     28.95
02:31:38        all     14.89      0.00     10.64      0.00      2.13     72.34
02:31:39        all      2.56      0.00      0.00      0.00      0.00     97.44
02:31:40        all      0.00      0.00      0.00      0.00      0.00    100.00
02:31:41        all      0.00      0.00      0.00      0.00      0.00    100.00

ОБНОВЛЕНИЕ 2 После предложений Йостена.

Ввод / вывод:

iotop терпит неудачу с OSError: Netlink error: No such file or directory (2) и sar -d также не справляется с Requested activities not available in file /var/log/sysstat/sa14. Я думаю, это потому, что это виртуальная машина, как и iostat тоже не получается. Может быть, это причина, почему %iowait сообщает sar 1 10 всегда 0%?

Загрузка процессора:

Процесс, превышающий% ЦП в htop на самом деле apache2. Я ожидал, что это может быть база данных, но это не так. Когда я делаю новый HTTP-запрос, он увеличивается до 94% за несколько секунд. Кажется, в этом виноват.

Я сделал strace -f -t и одно резюме strace -c -f. Кажется, очень много lstat вызывает (57786), при этом 2455 приводит к ошибкам. Не знаю, нормально ли это. Помимо этого, самый верхний вызов был wait4 что, как я полагаю, нормально (это просто ожидание), и munmap. Топ 5 ниже.

% time     seconds  usecs/call     calls    errors syscall
------ ----------- ----------- --------- --------- ----------------
 51.06    0.124742         897       139         6 wait4
 14.90    0.036388           1     57786      2455 lstat
  9.67    0.023622          13      1857           munmap
  7.69    0.018790          37       514           brk
  6.70    0.016361         481        34           clone
  2.87    0.006999          74        94        12 select

strace сам по себе замедлил apache в 2 раза. Сейчас я пытаюсь разобраться в длинной трассировке, чтобы увидеть, есть ли что-нибудь, указывающее на то, что вызывало скачок производительности процессора в течение нескольких секунд.

Какое типичное время для lstat для хорошо работающего сервера? Я хочу собрать некоторую информацию, чтобы я мог конструктивно пожаловаться поставщику, если это ошибка доступа к хранилищу.

ОБНОВИТЬ Выход fio тест случайного чтения:

random-read: (g=0): rw=randread, bs=4K-4K/4K-4K, ioengine=sync, iodepth=1
fio 1.59
Starting 1 process
random-read: Laying out IO file(s) (1 file(s) / 128MB)
Jobs: 1 (f=1): [r] [100.0% done] [12185K/0K /s] [2975 /0  iops] [eta 00m:00s]
random-read: (groupid=0, jobs=1): err= 0: pid=24264
  read : io=131072KB, bw=10298KB/s, iops=2574 , runt= 12728msec
    clat (usec): min=119 , max=162219 , avg=380.34, stdev=957.37
     lat (usec): min=119 , max=162219 , avg=380.89, stdev=957.40
    bw (KB/s) : min= 7200, max=13424, per=99.89%, avg=10285.72, stdev=1608.68
  cpu          : usr=2.80%, sys=18.65%, ctx=33511, majf=0, minf=23
  IO depths    : 1=100.0%, 2=0.0%, 4=0.0%, 8=0.0%, 16=0.0%, 32=0.0%, >=64=0.0%
     submit    : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
     complete  : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
     issued r/w/d: total=32768/0/0, short=0/0/0
     lat (usec): 250=45.57%, 500=37.17%, 750=3.41%, 1000=7.83%
     lat (msec): 2=5.67%, 4=0.27%, 10=0.08%, 20=0.01%, 250=0.01%

Run status group 0 (all jobs):
   READ: io=131072KB, aggrb=10297KB/s, minb=10545KB/s, maxb=10545KB/s, mint=12728msec, maxt=12728msec

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

cpu          : usr=0.19%, sys=0.59%, ctx=32923, majf=0, minf=23

В usr процент кажется небольшой частью того, что сообщается на моем сервере.

ОБНОВИТЬ Re PHP APC. Да, он установлен. Вывод из phpinfo:

APC Support enabled
Version 3.1.7
APC Debugging   Disabled
MMAP Support    Enabled
MMAP File Mask  no value
Locking type    pthread mutex Locks
Serialization Support   php
Revision    $Revision: 307215 $
Build Date  May 2 2011 19:00:42

Есть ли какой-то конкретный параметр, который я должен проверить? Это настройки, которые у меня есть (локальное значение, главное значение):

apc.cache_by_default    On  On
apc.canonicalize    On  On
apc.coredump_unmap  Off Off
apc.enable_cli  Off Off
apc.enabled On  On
apc.file_md5    Off Off
apc.file_update_protection  2   2
apc.filters no value    no value
apc.gc_ttl  3600    3600
apc.include_once_override   Off Off
apc.lazy_classes    Off Off
apc.lazy_functions  Off Off
apc.max_file_size   1M  1M
apc.mmap_file_mask  no value    no value
apc.num_files_hint  1000    1000
apc.preload_path    no value    no value
apc.report_autofilter   Off Off
apc.rfc1867 Off Off
apc.rfc1867_freq    0   0
apc.rfc1867_name    APC_UPLOAD_PROGRESS APC_UPLOAD_PROGRESS
apc.rfc1867_prefix  upload_ upload_
apc.rfc1867_ttl 3600    3600
apc.serializer  default default
apc.shm_segments    1   1
apc.shm_size    32M 32M
apc.slam_defense    On  On
apc.stat    On  On
apc.stat_ctime  Off Off
apc.ttl 0   0
apc.use_request_time    On  On
apc.user_entries_hint   4096    4096
apc.user_ttl    0   0
apc.write_lock  On  On

ОБНОВИТЬ Вырос apc.shm_size до 96М. Счетчик полного кэша теперь равен 0, и 96,5% попаданий в кеш после нескольких обновлений веб-сайта здесь и там. Объем памяти APC составляет 25,4 МБ.

Кажется, время загрузки сократилось примерно на 3 секунды, а теперь до 4-5 секунд, если я сделаю чистый wget с самого сервера без получения изображений и т. д. Все еще более чем в два раза медленнее, чем на другом хостинге, но определенно было улучшением.

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

Вы должны сначала определить, в чем проблема; если это PHP, MySQL, ввод-вывод, нагрузка, память, процессор, ядро ​​и т. д. sar регистрирует системные метрики; вам придется поймать это с поличным. Вы можете настроить atop вести учет процессов, что определенно помогает.

Чтобы определить, является ли это ввод / вывод

Используйте такие инструменты, как iotop и atop чтобы узнать, как используется диск; эти инструменты также расскажут вам, что вызывает ввод-вывод. Как правило, если iowait устойчивый более 10% это может быть проблемой.

sar регистрирует ввод-вывод диска; так что ты можешь бежать sar -d чтобы увидеть это (посмотри на %util столбец).

Чтобы определить, загружен ли он

Используйте такие инструменты, как htop, top, uptime; снова свяжите это с запущенным процессом и узнайте более подробную информацию о том, что делает процесс. Обратите внимание, что это сообщает о нагрузке на планировщик; это не отражает использование ЦП.

Чтобы определить, процессор ли это

sar снова приходит, чтобы спасти положение; вы можете увидеть эту информацию с помощью sar -P ALL. Вы также можете использовать mpstat -P ALL для данных в реальном времени. Как правило, ЦП является проблемой только в том случае, если все ЦП работают на 100%; 80% + означает, что они используются (но не обязательно насыщены).

Чтобы определить, является ли это память (ВМ)

Вы захотите использовать vmstat; vmstat -S M 1 и соблюдать swap, io, и system столбцы. Очевидно, что большое количество подкачки может повлиять на производительность. Также есть system раздел; большое количество прерываний также может делать то же самое.

Чтобы определить, прерывает ли он

Ты можешь использовать vmstat -S M 1. К сожалению, трудно сказать, являются ли прерывания проблемой, если в вашей системе нет исходный уровень на что нормально. Большое количество прерываний (вызванных аппаратным обеспечением, требующим действий со стороны ядра) заставит систему «сканировать». Неудачные сетевые адаптеры печально известны тем, что делают это.

Чтобы определить, ядро ​​ли это

Это сложнее, но обычно требует strace, perf, или sysdig инструменты. Одним из таких инструментов является perf top. strace с резюме (-c) приятно, но не разбивает его относительно системных ресурсов (так что предоставленные данные являются лишь предположениями); это идеально для использования perf top прийти к выводу, что это ядро. Вы также можете использовать stap (SystemTap), если ваш компьютер поддерживает его. Я также должен отметить, что strace повлияет на производительность; ты должен использовать sysdig если система вообще важна.

Чтобы определить, является ли это MySQL / PHP

Вы в основном должны следовать тому, что я написал выше (perf например, может предоставить информацию о том, какая команда вызывает большое время ядра, iotop, atop, htop может предоставлять информацию относительно системных ресурсов о том, что их использует); в основном, вы используете вышеуказанные инструменты, чтобы определить причину нагрузки.

Как только вы определили, что это MySQL

Это может быть запрос, который вы выполняете (поэтому вы захотите использовать EXPLAIN по этому запросу в MySQL). Вам также необходимо убедиться, что ваша база данных оптимизирована и запросы, которые вы выполняете, оптимизированы. Вы также должны убедиться, что движок таблиц, который вы используете, идеально подходит для того, что вы делаете (я видел много больших таблиц, использующих MyISAM, хотя они должны быть InnoDB). Если вы определили, что ничего из вышеперечисленного не является проблемой, и все еще подозреваете, что MySQL, вы можете захотеть заархивировать данные в затронутых таблицах, чтобы уменьшить доступ (сканирование таблиц) к этой таблице. Вы также можете проверить согласованность ограничений, включить буферизацию кеша и убедиться, что индексы оптимальны.

Хорошим инструментом для помощи в этом процессе является mytop; но вся информация, что mytop обеспечивает легко доступный в mysql клиент. Некоторые полезные операторы для запуска:

  • SHOW FULL PROCESSLIST\G чтобы получить на сервере полный список выполняемых в данный момент операторов SQL, а также их статус.
  • SHOW ENGINE INNODB STATUS\G (Только InnoDB)
  • EXPLAIN EXTENDED <QUERY> чтобы объяснить запрос, который выполняется MySQL.
  • SHOW GLOBAL STATUS\G для общесерверного статуса

Как только вы определили, что это PHP

Вы можете использовать инструменты для профилирования вашего PHP-кода (например, xdebug), а затем откройте созданный профиль в KCacheGrind чтобы увидеть анализ производительности профилированного кода PHP.

Если вы обнаружите, что это не так, возможно, вам просто нужно обновить сервер.

Одним из основных источников ввода-вывода для сайтов с интенсивным трафиком является /tmp Ввод / вывод, происходящий из:

  1. /tmp читается для данных сеанса php для многих систем CMS, таких как WordPress, при каждом переходе страницы, чтобы определить, имеет ли посетитель право доступа к новой странице

  2. /tmp много раз записывается / читается для любого SQL SELECT, в котором возвращаемые данные или любые созданные временные выбранные наборы находятся в / tmp

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

(используется верхняя память + используется своп) * 2

Затем на новой машине я настраиваю /tmp вбежать tmpfs (память) + использование mysqltuner (каждые несколько дней) + настраивать mysql (действительно mariadb) до mysqltuner в основном тихо.

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

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

При настройке я всегда начинаю с инструмента, который сообщает мне текущее состояние.

Поэтому для изменения размера памяти используйте top (память + подкачка + загрузка).

Для Apache, проверьте журналы, чтобы убедиться, что в них нет таких сообщений, как превышение MaxRequestWorkers.

Для старых PHP версии используют монитор APC, чтобы убедиться, что APC действительно работает + имеет достаточно свободной памяти + высокий процент попаданий - 90% + - хорошая цель.

Для современных версий PHP сделайте то же самое для Opcache, который несколько лет назад пришел на смену APC.

Для MySQLсначала переключитесь на MariaDB (по моему опыту, намного быстрее) + используйте mysqltuner каждые несколько дней, пока не получите достаточно тихий вывод.

Для CMS как и WordPress, никогда не верьте никому на слово, чтобы узнать, какой плагин кэширования работает. Используйте ab для проверки скорости сайта, сначала без кеширования + добавьте плагин кеширования + повторное тестирование.

Подсказка: начните с ZenCache + и вы удивитесь.

Наконец, я имитирую медиллорис DDOS атаковать каждый новый сервер, который я настраиваю, поскольку поведение DDOS работает по-разному в зависимости от схемы сети + скорости адаптера + ресурсов машины. Я настраиваю системы так, чтобы они выдерживали атаки DDOS достаточно долго, чтобы коды состояния Apache 4xx (обычно 400 + 408) отображались в журналах Apache + использую fail2ban для блокировки этих IP-адресов.

Большая часть настройки ввода-вывода - это создание необычных ситуаций загрузки, таких как slowloris DDOS, перед развертыванием любых сайтов на машине. Таким образом, вы можете настраиваться на досуге, вместо того, чтобы пытаться настраиваться под реальной нагрузкой, такой как расходы на рекламу или получение Slashdotted ... или под атакующей нагрузкой, такой как DDOS или High Value Attack, или просто злой скребок, который игнорирует ваш robots.txt + высасывает все ресурсы из вашей машины.

Оглянись ответ, который я дал на другой вопрос похож на этот для подсказок.

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

  1. Когда вы перенесли свой код WordPress в новую настройку, удостоверились ли вы, что правильно установили все пути в файловой системе в wp-config.php? Причина в том, что иногда WordPress может работать, несмотря на неправильные пути, если они установлены в параметрах MySQL DB для WordPress. Убедившись, что они в wp-config.php заставляет WordPress использовать правильные каталоги и гарантирует, что временные папки и папки кеша работают должным образом.
  2. Замедление работы базы данных? Это единственное, что я могу сказать, что было бы характерно для WordPress, но позволяло загружать другие страницы. Вы уверены, что ваш MySQL my.cnf работает должным образом для нужд БД вашего сайта?
  3. Есть ли в вашем коде WordPress плагин или параметр, позволяющий использовать сжатие Gzip? В целом сжатие Gzip должно происходить на стороне сервера через Apache или Ngnix, поскольку они могут выполнять сжатие Gzip более эффективно, чем код PHP. Так что, если у вас включено кеширование в WordPress, отключите его, поскольку PHP (который использует WordPress) не очень хорош для сжатия Gzip.

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

РЕДАКТИРОВАТЬ: Вот еще одна идея. Есть ли у вас авторизация Apache (htaccess) где-нибудь в вашей настройке? У вас настроено разрешение от localhost? Увидеть ниже. Иногда эта настройка работает, но если Allow from localhost является первым в списке AllowИли единственный элемент в списке AllowЭто может задохнуться от странности обратного DNS. Я бы порекомендовал попробовать отключить это - если вы можете - и посмотреть, насколько быстро загружается сайт по сравнению с тем, как он был включен.

Order Deny,Allow
Deny from all
Allow from 127.0.0.1 ::1
Allow from localhost

Это похоже на другие случаи, которые я видел, когда Apache тратит много времени на компиляцию PHP. Вы убедились, что установлен кеш-код операции (например, APC)? Он будет отображаться как загруженный модуль на выходе phpinfo(), если это поможет. В противном случае, чтобы отслеживать, что делает Apache в mod_php, лучшим вариантом будет XHProf.

Для всех, кроме jbx, прибывающих сюда через Google: кстати, другие ответы отличные. Иди прочитай их. Но эти ответы и ответы jbx на них помогли мне прийти к такому выводу.