PHP + Apache долгое время ожидания

Я наткнулся на небольшую кирпичную стену с устранением неполадок моего специального веб-сервера. Недавно мой сайт набрал количество запросов в секунду, и он упал.

Оригинальная коробка имела 8 ГБ оперативной памяти, 8-ядерный Xeon E3-1230, 1 ТБ 7200 об / мин диск (без рейда), 100 Мбит выделенной сети.

После всплеска я увеличил объем ОЗУ до 24 ГБ, чтобы поддерживать более одновременных пользователей.

Apache, кажется, справляется хорошо, даже с 3000 одновременно работающих пользователей, он очень быстро вернет HTML и статический контент (без кэширования).

Для дальнейшего тестирования различий между Apache/HTML и Apache/PHP я запустил ab,

И то и другое test.html а также test.php имеют одинаковый статический контент, PHP не вызывает includeс и не соединяется с MySQL.

Тест HTML

ab -n 500 -c 50 http://www.~~.com/test.html

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:      252  375 190.3    276    1399
Processing:   254  354 121.5    282     657
Waiting:      253  353 121.4    280     653
Total:        510  730 231.7    573    1675

Тест PHP

ab -n 500 -c 50 http://www.~~~.com/test.php

Connect:      248  275  51.1    267    1316
Processing:   256 4167 6210.2   2262   41489
Waiting:      253 4166 6210.2   2262   41489
Total:        509 4442 6212.4   2523   41754

Pingdom также сообщает о длительном времени ожидания при доступе к скрипту PHP.введите описание здесь

Я получаю аналогичный результат на WebPageTest.org, хотя лучше, когда первый байт - F:

           Load Time   **First Byte**   Start Render    DOM Elements    Time    Requests    Bytes In    Time    Requests    Bytes In
First View  2.061s  **0.839s**  0.000s  55  2.061s  20  428 KB  2.061s  20  430 KB

Вот мой top Результаты:введите описание здесь

I / O Test

При большой нагрузке wa% может увеличиться до 95% за несколько миллисекунд.

Я запускал iostat во время загрузки:

avg-cpu:  %user   %nice %system %iowait  %steal   %idle
           8.37    0.00    5.18    0.56    0.00   85.88

Device:         rrqm/s   wrqm/s   r/s   w/s   rsec/s   wsec/s avgrq-sz avgqu-sz   await  svctm  %util
sda               0.00     0.00  0.00  0.00     0.00     0.00     0.00     0.00    0.00   0.00   0.00
sda1              0.00     0.00  0.00  0.00     0.00     0.00     0.00     0.00    0.00   0.00   0.00
sdb               0.00    45.50  3.00 48.00   136.00   748.00    17.33     3.05   59.76   2.53  12.90
sdb1              0.00     0.00  0.00  0.00     0.00     0.00     0.00     0.00    0.00   0.00   0.00
sdb2              0.00     0.00  0.00  0.00     0.00     0.00     0.00     0.00    0.00   0.00   0.00
sdb3              0.00    45.50  3.00 48.00   136.00   748.00    17.33     3.05   59.76   2.53  12.90

avg-cpu:  %user   %nice %system %iowait  %steal   %idle
           4.00    0.00    3.56    0.69    0.00   91.75

Device:         rrqm/s   wrqm/s   r/s   w/s   rsec/s   wsec/s avgrq-sz avgqu-sz   await  svctm  %util
sda               0.00     0.00  0.00  0.00     0.00     0.00     0.00     0.00    0.00   0.00   0.00
sda1              0.00     0.00  0.00  0.00     0.00     0.00     0.00     0.00    0.00   0.00   0.00
sdb               6.00   118.50  9.50 21.00   996.00  1116.00    69.25     0.29    9.44   1.66   5.05
sdb1              0.00     0.00  0.00  0.00     0.00     0.00     0.00     0.00    0.00   0.00   0.00
sdb2              0.00     0.00  0.00  0.00     0.00     0.00     0.00     0.00    0.00   0.00   0.00
sdb3              6.00   118.50  9.50 21.00   996.00  1116.00    69.25     0.29    9.44   1.66   5.05

Для меня это не выглядит плохо, но я могу что-то упустить.

я использую FCGI

<IfModule mod_fcgid.c>
FcgidMaxRequestLen 1547483648
FcgidMaxRequestInMem 52485760
FcgidIdleScanInterval 15000
FcgidBusyTimeout 15000
FcgidProcessLifeTime 7200
FcgidConnectTimeout 1800
FcgidIOTimeout 1800
PHP_Fix_Pathinfo_Enable 1
FcgidMaxRequestsPerProcess 1000
</IfModule>

А вот и мой Apache Conf (я использую 2.4.x)

Timeout 60
TraceEnable Off
ServerSignature Off
ServerTokens ProductOnly
FileETag None
StartServers 10
<IfModule prefork.c>
MinSpareServers 5
MaxSpareServers 15
</IfModule>
<IfModule itk.c>
MinSpareServers 5
MaxSpareServers 15
</IfModule>
ServerLimit 2200
MaxRequestWorkers 2000
MaxConnectionsPerChild 15000
KeepAlive On
KeepAliveTimeout 1
MaxKeepAliveRequests 2000

Я просмотрел свои журналы ошибок Apache и журналы доступа. Ничего странного, чтобы сообщить.

Я действительно чешу голову здесь.

Я пытался отключить брандмауэр.

Я пытался увеличить Макс подключений.

Я оптимизировал MySQL и удалил много медленных запросов (которые были>0,5 с).

Что еще я могу сделать, есть ли что-то, что я могу использовать, чтобы помочь идентифицировать проблемы? Любая помощь будет принята с благодарностью.

PS:

Стоит отметить, что даже при интенсивном доступе к серверу PHPMyAdmin и cPanel по-прежнему очень отзывчивы. Ничто другое, кажется, не отстает, кроме PHP на сайте.

2 ответа

Решение

Я думаю, что ваша проблема - просто ваш жесткий диск с временем доступа. Apache может кэшировать html-страницы в памяти, но php-скрипты не кэшируются; необходимость быть выполненным каждый раз снова. Поэтому вызывается интерпретатор php, который читает скрипт с жесткого диска. Это занимает много времени. Самая медленная вещь на вашем сервере - ваш жесткий диск. На моем компьютере существует крайняя разница между приложениями, начиная с моего SSD и моего HDD (SSD работает до 10 раз быстрее!). Если ваш жесткий диск работает, то задержка выполнения скрипта php может резко возрасти.

Возможные решения: получите SSD (возможно, небольшой, только для часто используемых данных, таких как сценарии) и минимизируйте вызовы сценариев (и обращения к HDD) на вашем сервере. Убедитесь, что файловая система дефрагментирована (обычно это делается автоматически). Если ваш php-скрипт часто создает одно и то же содержимое, попробуйте кэшировать их в html-файл.

Этот ответ также может помочь вам: https://stackoverflow.com/questions/4181865/apache-php-caching

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

PHP OTOH на самом деле довольно "тяжелый" вариант: это целый интерпретатор (компилятор байт-кода?). А поскольку вы используете параллельное тестирование (-c), кто знает, насколько хорошо к нему мультиплексированы запросы? Это вовсе не проблема apache, а проблема PHP.

Что бы я сделал:

  1. Переключитесь на Apache MPM (многопоточный в нескольких процессах).

  2. Сделайте последовательный тест (без нескольких одновременных запросов), сравните.

  3. Бежать valgrind или что-то подобное в процессе Apache и посмотреть, где больше всего процессорного времени (Apache или PHP).

  4. запустить тот же тест, но обслуживая эту страницу через nginx. Поскольку nginx основан на асинхронной модели и очень быстр, то, если вы получите схожие результаты, виновником является PHP.

  5. Наконец, вы можете установить Zend Optimizer (30-дневная пробная версия бесплатно) или что-то вроде этого: https://github.com/zendtech/ZendOptimizerPlus.

Действительно, сравнение подачи статического файла с динамически генерируемой веб-страницей - это своего рода сравнение яблок и апельсинов. Ни одно из типичных решений (Python mod-apache, Django, PHP и т. Д.) Не будет очень быстрым в этом отношении, по крайней мере, по сравнению с обработкой статического файла. Node.js, возможно, является исключением из-за своего рода "низкоуровневой" веб-страницы программирования непосредственно в асинхронной модели.

PS ты не цитировал php.ini содержание. Опубликовать и / или настроить его.

Другие вопросы по тегам