Мы используем NGINX и php-fpm.
Мы заметили, что некоторые запросы зависают на долгое время (10+, 20+ минут...) черезвершинакоманда.
Также в записи журнала доступа (NGINX) были обнаружены некоторые подозрительные запросы (я имею в виду ботов), но я не уверен, имеют ли эти подозрительные запросы какое-либо отношение к тем запросам, которые зависли, или нет.
Итак, мой главный вопрос:
Можно ли (через конфигурацию или как-то еще) связать php-fpm PID с записью URL в журнале доступа?
Или есть какой-нибудь инструмент, который мог бы помочь мне с этой задачей?
Дополнительная информация:
У нас есть исходный код, поскольку мы являемся основными разработчиками.
Заранее спасибо!
решение1
Со стороны nginx проблематично определить правильный процесс php-fpm, поскольку по сути вы взаимодействуете с черным ящиком через сокет unix или сокет tcp, не говоря уже о потоках.
Вы можете атаковать проблему со стороны php. Вы можете использовать getmypid() из вашего php-скрипта, или, если это не ваш код, вы можете использовать опцию php_value auto_prepend_file в конфигурации php fpm. Таким образом, вы можете вставить свой собственный код в начало каждого php-файла и регистрировать pid вместе с соответствующим REQUEST_URI по своему усмотрению. У вас есть желаемое соединение. Однако будьте готовы к большим iops на загруженном сайте...
Если вам нужен только pid, может быть проще включить php-status, как описано здесьhttps://easyengine.io/tutorials/php/fpm-status-page/и проверьте yourserver/php-status?full
решение2
Обычно такие проблемы решаются с помощью так называемой RequestId
простой установки двух заголовков: X-REQUEST-ID
и X-CORRELATION-ID
и добавления их в логи как на стороне nginx, так и на стороне php.
RequestId
должен быть установлен на случайное значение (я использую UUID) в начале каждого запроса и CorrelationId
должен быть установлен на случайное значение при каждом взаимодействии пользователя. Для небольших веб-сайтов обычно есть только один RequestID
и один CorrelationId
. Если вы используете микросервисы, то каждый микросервис будет генерировать свой собственный RequestId
, но CorrelationId
будет общим для них.
Реализация зависит от вашей инфраструктуры, но простая реализация может выглядеть так:
# in nginx config
location / {
proxy_pass http://upstream;
proxy_set_header X-Request-Id $request_id;
...
}
# or
location / {
fastcgi_pass unix:/path/to/socket;
fastcgi_param HTTP_X_REQUEST_ID $request_id;
...
}
# This works because nginx generates a random string and stores it as $request_id
Затем просто зарегистрируйте свой pid в PHP:
# in php-fpm config
# %p - pid
access.format = "[%p][%{HTTP_X_REQUEST_ID}e] %R - %u %t \"%m %r\" %s"
# or in php application itself
# index.php
<?php
file_put_contents('somewhere.log', sprintf('[%s][%d]', $_SERVER['HTTP_X_REQUEST_ID'] ?? 'N/A', getmypid()), FILE_APPEND);
...
решение3
Если у вас включена страница статуса php-fpm, вы можете рассмотреть возможность проверки полного режима для отслеживания pid. Например, используяhttp://example.com/phpfpm-status?fullДолжна быть возможность выяснить, что происходит. (Примечание по безопасности: никогда не следует оставлять такие страницы статуса в открытом доступе.)
решение4
Вам следует использовать функцию PHP-FPM Slow-Log: Настройка, request_slowlog_timeout
а также slowlog
— см.Документация по конфигурации php-fpm- должен предоставить вам трассировку стека всех длительно работающих процессов php-fpm, включая их PID.