Chapter 1. Описание проблемы и её решение.
Настроена связка NGINX + PHP-FPM. PHP-FPM слушает обращения работает через unix socket:
listen.owner = php listen.group = php listen.mode = 666 listen = /var/run/php-fpm.sock listen.backlog = 65535
Операционная система CentOS 6.5
NGINX настроен принимать входящие соединения на адресе test.local и передавать их на PHP-FPM
server { server_name test.local; root /home/vhosts/test; location / { fastcgi_pass unix:/var/run/php-fpm.sock; include fcgi-as.fconf; } }
Параметры в fcgi-as.fconf всегда отдают все обращения файлу index.php
В файле index.php прописан маленький скрипт для теста:
<? $a = 0; for ($i = 0; $i < 100; $i++) { $a++; } echo $a; ?>
Для тестирования производительности используется программа OpenLoad — http://openwebload.sourceforge.net/
Программа собрана из исходников, для сборки пришлось её немного пропатчить, так как она во первых не компилировалась, а во вторых нельзя было указать дополнительные параметры для gcc через configure.
В файле /src/tmplchunk.h меняем строку:
virtual int CTmplChunk::Verify(const char*& pos, const char* parm);
На строку
virtual int Verify(const char*& pos, const char* parm);
После выполнения configure в файле /src/Makefile меняем строку:
CXXFLAGS = -g -O2
На строку:
CXXFLAGS = -g -O3 -march=native
Этого можно и не делать, но тогда программа немного подтормаживает и выполняет на 3-5% запросов меньше.
Важно: Не пытайтесь использовать openload или любую другую программу для тестирования Вашего сервера на windows, на этой OS Вы скорее упретесь в производительность Вашей windows машины чем в производительность Вашего сервера, а результаты не будут достоверными.
Выполняем компиляцию программы
configure
[Патчим файлы]
make make install
И начинаем тестирование. Параметры программы:
openload [опции] URL [кол-во клиентов] ОПЦИИ: -t - Режим тестирования, в этом режиме не будет производиться тестирования производительности, а вместо этого будет отображен полный ответ от сервера включая заголовки. Это может быть полезно если Вы хотите проверить правильность введенного URL. -h header value - Дополнить каждый запрос заголовком header со значением value -h User-Agent "MSIE 5.0" -l time - время time в секундах в течении которого выполнять тестирование -o outputmode - режим вывода результата, в данный момент поддерживается только csv ОПИСАНИЕ РЕЗУЛЬТАТА: MaTps - Скользящее среднее значение TPS за последние 20 секунд. Tps - Кол-во запросов которые клиенты успели выполнить за последнюю секунду Resp Time - Серднее время ответа по всем запросам за последнюю секунду Err - Процент запросов которые были выполнены с ошибкой (код ответа HTTP отличный от 200) Count - Общее кол-во выполненных запросов с начала тестирования Total TPS - Среднее значение TPS за все тестирование Avg. Response Time - Среднее время ответа за все тестирование в секундах Max. Response Time - Максимальное время ответа за все тестирование в секундах
Выполняем команду:
openload -l 1 http://test.local 1
Пока всё хорошо:
URL: http://test.local:80/ Clients: 1 Time Limit: 1 sec. MaTps 1060.00, Tps 1060.00, Resp Time 0.001, Err 0%, Count 1060 Total TPS: 1058.94 Avg. Response time: 0.001 sec. Max Response time: 0.009 sec Total Requests: 1060 Total Errors: 0
Усложняем задачу:
openload -l 1 http://test.local 200
И получаем проблему:
URL: http://test.local:80/ Clients: 200 Time Limit: 1 sec. MaTps 1613.00, Tps 1613.00, Resp Time 0.120, Err 13%, Count 1613 Total TPS: 1531.81 Avg. Response time: 0.120 sec. Max Response time: 0.320 sec Total Requests: 1613 Total Errors: 214
В логе nginx видим строчки:
2014/10/17 12:52:34 [error] 8740#0: *720283 connect() to unix:/var/run/php-fpm.sock failed (11: Resource temporarily unavailable) while connecting to upstream,
Проиходит это потому что операционная система отвергает попытки nginx подключиться к unix сокету.
Причина либо превышено максимальное кол-во соединений к сокету либо максимальное кол-во не обработанных соединений к сокету.
Проверяем лимиты:
sysctl net.core
Нас интерисуют строки:
net.core.somaxconn = 128 net.core.netdev_max_backlog = 200
Из-за них и происходит ошибка, так как максимальное кол-во соединений 128 а максимум не обработанных 200
Меняем лимиты, в файл /etc/sysctl.conf прописываем строки
net.core.somaxconn = 20000 net.core.netdev_max_backlog = 65535
Применяем параметры
sysctl -p
Перезапускаем php-fpm
service php-fpm restart
Запускаем наше тестирование:
openload -l 1 http://test.local 200
Видим что все в порядке:
URL: http://test.local:80/ Clients: 200 Time Limit: 1 sec. MaTps 1423.00, Tps 1423.00, Resp Time 0.133, Err 0%, Count 1423 Total TPS: 1421.58 Avg. Response time: 0.133 sec. Max Response time: 0.276 sec Total Requests: 1423 Total Errors: 0
Вот и все, проблема решена, а заодно мы получили замечательную утилиту openload для последующего тестирования и оптимизации производительности нашего сервера.