Один из способов оптимизации приложений — это распределения задач.
Как правило, во многих проектах делают ставку на встроенный планировщик типа — CRON, который методично выполняет определенный набор скриптов. В годами данный планировщик обрастает такими «костылями», что переписать все с нуля оказывается гораздо проще, чем разобраться как же «это все» работает. Дополнительные проблемы создают распределенные системы.
Решение простое — уход в сторону систем распределения задач, одной из которых является Gearman.
Gearman это универсальный фреймворк разработки приложений для раздачи работ множеству машин или процессов. Это позволяет приложениям выполнять задачи параллельно, распределяя нагрузку и использовать функции различных языков. Фреймворк может использоваться во множестве приложений, от высоконадежных веб-сайтов до транспорта событий репликации базы данных.
Gearman в своей работе, работает с тремя компонентами:
- сервер задач — сюда будут приходить задачи и результаты от клиентов и исполнителей, отсюда же будут высылаться задания и результаты, исполнителям и клиентам соответственно.
- исполнитель — основная часть, где необходима реализация какой-либо функциональности. Исполнитель принимает и пытается выполнить задание от сервера.
- клиент — создаёт и отсылает задачу на сервер и получает результат.
В своей работе я использую связку Gearman+php, задания хранятся в mysql, для того чтобы исключить возможные проблемы при пропадании электричества, а также для отслеживания очереди задач.
Установка на клиенте:
Для того, чтобы избежать ругани со стороны системы "configure: error: Please install libgearman" и подобные, ставим необходимые компоненты: #yum install php-pear re2c libgearman libgearman-devel php-devel gcc Обновляем pecl и ставим gearman: #pecl channel-update pecl.php.net #pecl install gearman
В случае успеха получаем сообщение вида:
Build process completed successfully Installing '/usr/lib64/php/modules/gearman.so' install ok: channel://pecl.php.net/gearman-1.1.2 configuration option "php_ini" is not set to php.ini location You should add "extension=gearman.so" to php.ini
Выполняем, что от нас требуют
echo "extension=gearman.so" > /etc/php.d/gearman.ini И делаем проверку: # php -i| grep gear /etc/php.d/gearman.ini, gearman gearman support => enabled libgearman version => 1.1.8
Установка серверной части:
Делаем примерно тоже самое, что описано выше, кроме того нам понадобиться непосредственно демон:
yum install gearman*
После установки, систему можно сразу опробовать, клиент ставит задачу, сервер её выполняет, для примера ниже php код:
Код клиента:
$mail = array( 'to' => 'test@gmail.com', 'subject' => 'Привет', 'body' => 'Это тестовое сообщение', ); # Подключаемся к серверу $client= new GearmanClient(); $client->addServer(); # Регистрируем задачу для фонового выполнения # "sendmail" - это тип задачи # $mail - это данные письма $result = $client->doBackground("sendmail", serialize($mail)); ?>
Код исполнителя:
<?php // Сохранение в $lock_file обязательно, иначе handle помрёт и файл автоматом закроется if(!flock($lock_file = fopen("robot.lock", 'w'), LOCK_EX | LOCK_NB)) die("Already runninng\n"); # Создаем "воркера" и подключаемся к серверу задач $worker= new GearmanWorker(); $worker->addServer(); # Регистрируем обработчик события "sendmail" # "send_mail" - это имя функции, объявленной ниже $worker->addFunction("sendmail", "send_mail"); while (1) { echo "Ждем работы...\n"; $ret= $worker->work(); if ($worker->returnCode() != GEARMAN_SUCCESS) break; } # Функция реальной отправки почты # В аргумент ей передается объект задачи function send_mail($job) { $workload= $job->workload(); $data = unserialize($workload); // mail($data['to'], $data['subject'], $data['body']); echo $data['to']." ".$data['subject']." ".$data['body']; }
Как правило, данных настроек достаточно, однако мне необходимо хранить события в базе, для этого необходимо создать базу gearman и в «/etc/sysconfig/gearmand» прописать следующий код, необходимая таблица создастся самостоятельно, при первом старте демона:
[root@sigma sysconfig]# cat /etc/sysconfig/gearmand ### Settings for gearmand # OPTIONS="" OPTIONS="--queue-type=MySQL \ --mysql-host=127.0.0.1 \ --mysql-user=gearman \ --mysql-password=gearman_password \ --mysql-db=gearman \ --mysql-table=gearman_queue \ --mysql-port=3306"
Более подробные сведения по настройке данного демона, в частности например для посылки заданий посредством http, можно получить из документации: http://gearman.org/manual/job_server/