PHP7.3-FPM с Apache: Неизвестный тайм-аут выполнения запроса скрипта

Я настроил Apache 2.4 MPM Event с PHP7.3-FPM на довольно загруженном веб-сервере следующим образом:

Timeout 90

<Proxy "unix:/run/php/php7.3-fpm.sock|fcgi://php-fpm">
    ProxySet disablereuse=on timeout=90
</Proxy>

<FilesMatch ".+\.php$">
        SetHandler proxy:fcgi://php-fpm
</FilesMatch>

Конфигурация PHP в /etc/php/7.3/fpm/php.ini установлена ​​на

max_execution_time=60

PHP-FPM настраивается в /etc/php/7.3/fpm/pool.d/www.conf для

request_terminate_timeout=90

Время ожидания чтения настраивается в /etc/apache2/mods-enabled/reqtimeout.conf следующим образом:

RequestReadTimeout header=20-120,minrate=50
RequestReadTimeout body=60-120,minrate=50

В журнале FPM теперь я вижу каждую минуту 1-2 рабочих для неизвестных запросов, которые убиваются через 90+ секунд.

[16-May-2019 09:25:32] WARNING: [pool www] child 105567, script '' (request: " ") execution timed out (113.002653 sec), terminating
[16-May-2019 09:25:32] WARNING: [pool www] child 105567 exited on signal 15 (SIGTERM) after 4050.136381 seconds from start
[16-May-2019 09:25:32] NOTICE: [pool www] child 110414 started

Если я не установлю request_terminate_timeout чтобы убить этих рабочих, они остаются дольше (~5 минут) в состоянии "Чтение заголовков" и блокируют пул PHP-FPM.

Кажется, потоки в Apache MPM не блокируются. Ничто не мешает максимальным рабочим ценностям.

Как я могу увидеть, к какому сценарию / запросу принадлежат эти работники PHP? Почему эти сценарии работают даже после max_execution_time 60 секунд истек? Как можно избежать блокировки пула PHP такими запросами?

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

1 ответ

Как упоминает @constantin-galbenu в своем комментарии , Apache<Proxy>Директива не очень хорошо сочетается с моделью многопроцессорной обработки prefork PHP-FPM, как описано в https://bugs.php.net/bug.php?id=69890 .

[2019-05-02 10:03 UTC] депутат на webfactory dot de

Для справки, в руководстве Apache по адресу https://httpd.apache.org/docs/current/mod/mod_proxy_fcgi.html#examples говорится:

Включить повторное использование соединений с серверной частью FCGI, например PHP-FPM.

Имейте в виду, что PHP-FPM (на момент написания статьи, февраль 2018 г.) использует модель prefork, а именно, каждый из его рабочих процессов может обрабатывать одно соединение одновременно. По умолчанию mod_proxy (настроенный с параметром Enablereuse=on) разрешает пул соединений ThreadsPerChild с серверной частью для каждого процесса httpd при использовании многопоточного MPM (например, работника или события), поэтому следует принять во внимание следующие варианты использования:

При загрузке HTTP/1.1 это, скорее всего, приведет к созданию подключений MaxRequestWorkers к серверной части FCGI.

При загрузке HTTP/2 из-за реализации mod_http2 возникают дополнительные рабочие потоки h2, которые могут принудительно создавать другие серверные соединения. Общее количество подключений в пулах может превысить значение MaxRequestWorkers.

Максимальное количество рабочих процессов PHP-FPM должно быть настроено с умом, поскольку существует вероятность того, что все они будут «заняты» обработкой простаивающих постоянных соединений без возможности создания новых, и опыт конечного пользователя ухудшится. быть кучей таймаутов HTTP-запросов.

Моя интерпретация заключается в том, что при включении Enablereuse=on каждый рабочий процесс/поток Apache MPM может иметь открытое соединение с PHP-FPM. На странице состояния PHP-FPM они будут отображаться как «Чтение заголовков...» (или подобное). Эти процессы кажутся активными (ожидающими) PHP-FPM и поэтому не завершаются.

Моя собственная проблема заключалась в том, что веб-серверы использовали модуль многопроцессорной обработки событий Apache (MPM), передающий выполнение PHP в PHP-FPM, используя пример конфигурации из документации Apache mod_proxy_fcgi :

      <FilesMatch "\.php$">
    # Note: The only part that varies is /path/to/app.sock
    SetHandler  "proxy:unix:/path/to/app.sock|fcgi://localhost/"
</FilesMatch>

# Define a matching worker.
# The part that is matched to the SetHandler is the part that
# follows the pipe. If you need to distinguish, "localhost; can
# be anything unique.
<Proxy "fcgi://localhost/" enablereuse=on max=10>
</Proxy>

В этой конфигурации я видел необъяснимые ошибки прокси-сервера 503 от Apache, при этом приложение периодически не отвечало, пока PHP-FPM не был перезапущен. После добавленияrequest_terminate_timeout = 5mмоему/etc/php-fpm.d/www.confЧтобы принудительно уничтожить длительные запросы PHP-FPM, мое приложение стало немного более стабильным, и я начал видеть ошибки, подобные следующим, в моих и менее частых сбоях, которые длились несколько минут, прежде чем восстанавливались без вмешательства:

      [04-Jan-2023 15:19:26] WARNING: [pool www] child 349975, script '' (request: " ") execution timed out (362.004673 sec), terminating
[04-Jan-2023 15:19:26] WARNING: [pool www] child 349975 exited on signal 15 (SIGTERM) after 1200.012433 seconds from start

После удаленияenablereuse=onфлаг из моей конфигурации Apache, я больше не вижу вышеуказанных ошибок тайм-аута в моем/var/log/php-fpm/error.log. Новая конфигурация:

      <FilesMatch "\.php$">
  <If "-f %{REQUEST_FILENAME}">
    # Pick one of the following approaches
    #
    # Use the standard TCP socket
    #SetHandler "proxy:fcgi://localhost:9000"
    # If your version of httpd is 2.4.9 or newer (or has the back-ported feature), you can use the unix domain socket
    #SetHandler "proxy:unix:/path/to/app.sock|fcgi://localhost/"
    SetHandler "proxy:unix:/run/php-fpm/www.sock|fcgi://localhost/"
  </If>
</FilesMatch>

# Defining a worker will improve performance
# And in this case, re-use the worker (dependent on support from the fcgi application)
# If you have enough idle workers, this would only improve the performance marginally
#
# enablereuse=on is only available in Apache >= 2.4.11
<Proxy "fcgi://localhost/" max=10>
</Proxy>
Другие вопросы по тегам