29.05.2013

Опрятные логи Nginx

Хочу поделиться своим вариантом формата access-лога. Очень уж мне нравится. Не могу держать в себе :)

        log_format verbose  '[$time_iso8601] || '
                            ' STATUS: $status || '
                            ' HOST: $host || '
                            ' CONN#: $connection || '
                            ' $remote_addr --> $server_addr || '
                            ' REQ_TIME: $request_time || '
                            ' UPSTR_RESP_TIME: $upstream_response_time || '
                            ' USER_AGENT: "$http_user_agent" || '
                            ;


18.05.2013

Как подцепиться к FastCGI-процессу напрямую

Как известно, telnet'ом тут не пообщаться. На помощь приходит утилита cgi-fcgi

Устанавливаем пакет, в котором она есть. Вариант для Debian:
apt-get install libfcgi0ldbl

У CentOS пакет называется, вроде как, fcgi.


Далее мы можем делать запросы скармливая его утилите cgi-fcgi либо прямо из командной строки либо помещая их в простой советский CGI-скрипт. Формат общения примерно следующий:

cgi-fcgi -bind -connect адрес:порт
Если не передавать никакой запрос или не передать минимально необходимые данные, то вернутся просто стандартные теги:

# cgi-fcgi -bind -connect 127.0.0.1:9000
X-Powered-By: PHP/5.4.4-14Content-type: text/html
Но нам нужно сделать какой-нибудь реальный запрос. Минимальный набор передававаемых переменных составляет:
REQUEST_METHOD - метод HTTP, например GET или POST
SCRIPT_FILENAME - полный путь с скрипту. Например: /var/www/index.php
более полный список стандартных переменных можно посмотреть например в файле /etc/nginx/fastcgi_params или в массиве $_SERVER в PHP.

Самый простой вариант - прямо в командной строке задать все переменные и обратиться к FastCGI-процессу:
# SCRIPT_FILENAME=/var/www/index.php
# REQUEST_METHOD=GET
# cgi-fcgi -bind -connect 127.0.0.1:9000

, где # - это приглашение командной строки и его писать не надо.


Ну и в помощь простейшая команда, которая выступит в качестве мониторинга количества процессов (не забудьте настрить парметр pm.status_path в pool.d/www.conf):
watch SCRIPT_NAME=/fpm-status SCRIPT_FILENAME=/fpm-status QUERY_STRING= REQUEST_METHOD=GET cgi-fcgi -bind -connect 127.0.0.1:9000



read data timeout in 40 seconds

Многие встречаются достаточно часто с этой ошибкой. Очень популярно мнение, что нужно увеличить параметр FcgidIOTimeout в конфиге FastCGI. Отчасти так оно и есть. 40 секунд - это дефолтное значение FcgidIOTimeout, если оно не задано в конфиге в явном виде.

Первое, на чем хотелось бы сделать акцент: FcgidIOTimeout - это время, которое отведено под то, что Апач пытается подсоединиться к приложению FastCGI. То есть это до того, как началось исполнение кода PHP и к PHP-интерпретатору и его ограничениям по времени никакого отношения не имеет. Поэтому не надо думать, что скрипту не хватает время для исполнения. На момент вылета этой ошибки, скрипт даже еще не начал исполняться - его никто не принимает в работу.

Причина сводится к простой фразе: Апачу не отвечает ни один из инстансов FastCGI. А это уже может иметь сколько угодно разных причин. Например FastCGI-процессы зависли или уперлись в лимит FcgidMaxProcessesPerClass (максимальное количество процессов на одного пользователя). В таком случае ждать можно вечно и накручивать время ожидания - бесполезно.

Вывод: искать в чем пробема нужно не глупым повышением цифры в FcgidIOTimeout, а выяснением, почему Апач не может обратиться к FastCGI аж в течении 40-ка секунд.