PHP - исключительно популярный язык программирования, до сих пор огромное количество проектов пишется именно на нем. Язык ругают за отвратительный дизайн, неудобный синтаксис, кривое поведение в спорных случаях, отсутствие нормальных средств отладки - но его популярность это никак не снижает. Самое страшное для админа - ситуация, когда на сильно нагруженном проекте начинает тормозить код. Стандартные средства отладки (xprof, xdebug) роняют производительность языка в яму (накладные расходы - вплоть до пятикратного падения скорости), и как отлаживать сложный код на живую - совершенно неясно. Именно для борьбы с такими проблемами придумана PINBA - расширение для мониторинга скорости кода. Тут я расскажу, как установить PINBA (клиент, сервер и интерфейс) на debian и что с ними потом делать.

Как это работает

В отличае от XProf PINBA практически не замедляет работу скрипта. В базовом варианте она не требует никакой модификации PHP кода и никак на его выполнение не влияет. Устройство очень простое, штатно PINBA состоит из двух частей. Во-первых - это PHP extenstion (pinba.so), который отслеживает время выполнения скрипта (а так же - адрес скрипта и URL, нагрузку на CPU, память и код завершения). По окончании выполнения запроса он отправляет данные на сервер pinba. Сервер - это MySQL, собранный со специальным плагином (libpinba.so). Сервер принимает на определенном порту UDP-датаграммы и складывает их в базу. Интерфейсом для чтения статистики служит MySQL, что позволяет сравнительно легко анализировать данные и писать к ним свои интерфейсы. Важно, что php extension (генератор) не проверяет целостность отправленных данных или качество их доставки - он просто считает и отправляет.

Вот как будет выглядеть наша инсталляция:

https://prudnitskiy.pro/media/uploads/pinba.png

Установка: клиент

В debian репозитории DotDeb есть нужный нам клиент (генератор статистики) и проще всего его прямо оттуда и поставить. Если у вас еще не установлен DotDeb - вот инструкция. После этого просто ставим пакет:

apt-get install -y php5-pinba

И настраиваем его, поправив файл /etc/php5/mods-available/pinba.ini

extension=pinba.so
pinba.enabled=1
pinba.server=172.16.10.10:30002

В этом примере предполагается, что сервер, собирающий статистику у нас имеет адрес 172.16.10.10 и порт 30002. После этого перезапускаем php и установка клиента на этом закончена.

Установка: сервер

С установкой сервера все несколько сложнее, так как пакет pinba-server есть только у dotdeb и он сломан. Его прийдется собирать из исходного кода. Для начала на сервер статистики поставим сам mysql. Это должен быть именно стандартный mysql, а не maria или percona:

apt-get install mysql-server-5.6 mysql-client-5.6 libmysqlclient18 libmysqlclient18-dev

Теперь поставим инструменты разработки, они потребуются нам, чтобы собрать пакет:

apt-get install build-essential protobuf-compiler libmysqlclient-dev \
libjudydebian1 libevent-dev libjudy-dev git libevent-2.0-5 libtool \
libevent-core-2.0-5 libevent-extra-2.0-5 libevent-openssl-2.0-5 \
libevent-pthreads-2.0-5 libprotobuf-dev libprotobuf-lite7 libprotobuf7 git-core

Переходим в tmp, выгружаем код pinba engine (сервер статистики) и исходный код mysql server:

cd /var/tmp
git clone 'https://github.com/tony2001/pinba_engine'
apt-get source mysql-server

Нам потребуется header-file от существующего mysql-сервера, скопируем. Я не знаю, какая версия mysql-server будет у вас, у меня это mysql-5.6-5.6.25.

 cp '/usr/include/mysql/mysql_version.h' /var/tmp/mysql-5.6-5.6.25/include/
 cp '/usr/include/mysql/my_config.h' /var/tmp/mysql-5.6-5.6.25/include/

Нам нужно узнать текущие опции сборки mysql:

OPTIONS="$(VISUAL=\"$(which 'cat')\" mysqlbug | grep 'Configured with' |  sed -e 's/.*configure -v //')"

Соберем модуль:

cd pinba_engine

./buildconf.sh

./configure ${OPTIONS} \
--with-mysql='${MYSQL_SOURCES}' \
--with-judy \
--with-protobuf \
--with-event \
--libdir='/usr/lib/mysql/plugin/'

make

make install

Библиотека собрана, теперь можно установить плагин на сервер и создать базу, где мы будем хранить статистику:

mysql --execute="INSTALL PLUGIN pinba SONAME 'libpinba_engine.so';" --user=root
mysql --execute="CREATE DATABASE pinba DEFAULT CHARACTER SET utf8 DEFAULT COLLATE utf8_unicode_ci;" --user=root
mysql --user=root 'pinba' < '/tmp/pinba_engine/default_tables.sql'
mysql --user=root --execute="grant all on pinba.* to [email protected] identified by 'Hkx77jg8t6zGw6J5'"

Теперь сообщим серверу настройки pinba. Для этого поправим /etc/mysql/my.cnf. В секции [mysqld] добавим следующее:

pinba_port = 30002
pinba_address = 172.16.10.10
pinba_stats_gathering_period = 10000
pinba_stats_history = 900
pinba_temp_pool_size = 10000
pinba_request_pool_size = 10000

Чтобы изменения вступили в силу - надо перезапустить mysql. Разумеется, порт UDP/30002 не должен быть заблокирован в firewall. Настройка сервера на этом закончена, будемт ставить интерфейс.

Установка: интерфейс

Эту роль у нас будет выполнять Intaro’s pinboard. Интерфейс довольно простой, но удобный и симпатичный. В принципе, его можно поставить на любой сервер, с которого есть доступ к mysql, в моем примере это будет тот же сервер, куда мы собираем статистику. Для работы pinboard потребуется nginx, php5 (версии не менее 5.5) и php composer. Установим:

apt-get install -y php5-cli php5-common php5-curl php5-fpm php5-gd php5-mysql nginx-full
curl -sS https://getcomposer.org/installer | php

Выгрузим код:

cd /var/www
git clone git://github.com/intaro/pinboard.git --branch=v1.5.2

Установим зависимости:

cd pinboard
php composer.phar install

Чтобы интерфейс знал адрес и параметры соединения с базой, поправим настройки в файле ‘config/parameters.yml’:

db:
    host: 127.0.0.1
    name: pinba
    user: pinbauser
    pass: Hkx77jg8t6zGw6J5

остальное менять не нужно. Мигрируем базу:

./console migrations:migrate

Добавляем задание в крон для агрегации данных:

./console register-crontab

Теперь осталось настроить nginx. Для этого создадим файл /etc/nginx/sites-enabled/pinba со следующим содержанием:

server {
    listen 80;
    server_name pinba.ourdomian;
    access_log /var/log/nginx/pinba.access.log;
    error_log /var/log/nginx/pinba.error.log;
    root /var/www/pinboard/web;

    location = / {
        try_files @site @site;
    }

    location / {
        try_files $uri $uri/ @site;
    }

    location ~ \.php$ {
       return 404;
    }

    location @site {
        fastcgi_pass unix:///var/run/php5-fpm.sock;
        include fastcgi_params;
        fastcgi_param  SCRIPT_FILENAME $document_root/index.php;
    }

    location ~ /\.(ht|svn|git) {
        deny  all;
    }
}

Теперь достаточно просто перезапустить nginx и можно пользоваться нашим новым интерфейсом. Важно понимать, что статистика агрегируется раз в N минут (частоту спросит сам pinboard при миграции данных), но данные в секции live доступны в любой момент.