Иногда наши сервисы должны выполнять огромные задачи после взаимодействия с пользователем. Например, нам нужно отправить письмо, сгенерировать файл отчета или вызвать внешние API. Такие задачи могут быть медленными из-за сторонних разработчиков и могут потреблять ресурсы вашего сервера.
В этом случае приложение может стать змеей, поедающей слона, как в книге «Маленький принц» . Вы берете некоторые данные у пользователя и заставляете его ждать, потому что змее нужно некоторое время, чтобы переварить слона (или что-то еще, что должно сделать ваше приложение):
Чтобы быстрее обрабатывать эту функцию, вам нужно сделать части приложения асинхронными . Этого можно добиться, делегировав эту задачу более мощному серверу или запустив его в фоновом режиме.
И Gearman является подходящим инструментом, который можно использовать для этого.
Что мы будем делать?
В этом руководстве мы создадим простое приложение, которое будет делегировать задачу от клиента работнику Gearman. Наше приложение будет вычислять последовательность Фибоначчи в трех процессах. Для запуска рабочих процессов мы установим и настроим Supervisor.
Обратите внимание, что для примеров из этого руководства необходим PHP7.
Так что же такое Gearman?
Во-первых, давайте узнаем, что Gearman с его домашней страницы :
Gearman предоставляет универсальную прикладную среду для переноса работы на другие машины или процессы, которые лучше подходят для этой работы. Это позволяет выполнять работу параллельно, обрабатывать балансировку нагрузки и вызывать функции между языками. Он может использоваться в различных приложениях, от веб-сайтов высокой доступности до транспорта событий репликации базы данных. Другими словами, именно нервная система взаимодействует с распределенной обработкой.
Другими словами, Gearman — это система очередей, которую легко масштабировать на многих серверах и которая гибка в использовании благодаря многоязыковой поддержке.
Установить Gearman
Если вы используете Debian / Ubuntu, выполните следующую команду, чтобы установить Gearman с необходимыми инструментами и расширением PHP:
1
|
sudo apt-get install gearman php-gearman gearman-tools
|
После этого запустите сервер Gearman и проверьте статус:
1
2
|
sudo gearmand -d
gearadmin —status
|
Но вы не увидите ничего полезного после команды status, потому что мы еще не создали ни одного рабочего. Просто запомни это, пока нам это не понадобится.
Создать клиента
И мы готовы запустить скрипт под названием client.php
. Этот скрипт создаст клиент Gearman и отправит информацию на сервер на том же компьютере:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
|
<?php
// create gearman client
$client = new GearmanClient();
$client->addServer(‘127.0.0.1’);
// config
$numbers = [
1, 2
];
// do a task with gearman worker
$res = $client->doNormal(‘get_sequence’, json_encode($numbers));
|
Возможно, вы заметили, что мы отправили числа в формате JSON. Клиенты и работники Gearman общаются друг с другом в строковом формате, поэтому одним из способов сериализации массива является использование функции json_encode()
или чего-то подобного.
Получив ответ от работника, мы рассмотрим его с помощью json_decode()
и json_decode()
виде строк CSV:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
|
<?php
// decode answer
$lines = json_decode($res, true);
if (empty($lines)) {
die(’empty answer’);
}
// output as csv
foreach ($lines as $numbers) {
$line = implode(‘, ‘, $numbers);
echo($line . PHP_EOL);
}
|
Мы только что закончили наш клиентский скрипт, поэтому давайте запустим его из терминала:
1
|
php /vagrant/tuts-gearman-supervisor/code/client.php
|
Но он застрянет без какого-либо вывода. Почему? Это ждет работника, чтобы соединиться.
Создать работника
Пришло время создать работника, который будет выполнять заказанную клиентом работу. Нам потребуется файл с функцией fibonacci()
и мы создадим нового работника Gearman на текущем сервере:
1
2
3
4
5
6
|
<?php
require_once __DIR__ .
$worker = new GearmanWorker();
$worker->addServer(‘127.0.0.1’);
|
После этого мы добавим новую функцию, названную так же, как мы ее называли в клиентском коде:
01
02
03
04
05
06
07
08
09
10
11
|
<?php
$worker->addFunction(‘get_sequence’, function ($job) {
// decode input
$content = $job->workload();
$data = json_decode($content, true);
// calculate sequence and return result
$rows = fibonacci($data);
return json_encode($rows);
});
|
И, конечно же, не забудьте обернуть свой ответ в формате JSON. Последнее, что нужно сделать, — это зациклить рабочий скрипт, чтобы использовать его много раз без перезапуска:
1
2
3
4
5
|
<?php
for ($i = 0; $i < 100; ++$i) {
$worker->work();
}
|
Мы можем запустить рабочий скрипт в фоновом режиме:
1
|
php /vagrant/tuts-gearman-supervisor/code/worker.php &
|
В этот момент вы, возможно, уже заметили, что клиентский скрипт закончил свою работу и написал что-то вроде этого:
1
2
3
4
5
6
|
vagrant@localserver:~$ /vagrant/tuts-gearman-supervisor/code/client.php
1, 2, 3
2, 3, 5
3, 5, 8
5, 8, 13
8, 13, 21
|
Проверьте статус Gearman
Наконец, у нас работает рабочий, поэтому мы можем проверить статус еще раз:
1
2
3
4
5
|
vagrant@localserver:~$ gearadmin —status
get_sequence 0 1 2
vagrant@localserver:~$ ps -aux |
root 4595 0.0 1.5 98928 7764 ?
root 4596 0.0 1.5 98928 7764 ?
|
В каждой строке есть имя функции и три числа: количество задач в очереди (0), количество запущенных заданий (1) и количество способных работников (2).
Конечно, чтобы добавить больше рабочих, вы можете запустить больше рабочих сценариев. Чтобы остановить каждого из них, вы можете использовать killall
. Но есть отличный инструмент для управления работниками, который называется Supervisor.
Несколько слов о супервайзере
Как сказано в руководстве:
Supervisor — это клиент-серверная система, которая позволяет пользователям отслеживать и контролировать ряд процессов в UNIX-подобных операционных системах.
Давайте установим его и создадим основной файл конфигурации:
1
2
|
sudo apt-get install supervisor
sudo nano /etc/supervisor/conf.d/supervisor.conf
|
В открывшемся редакторе мы создадим базовую конфигурацию для работника Gearman:
1
2
3
4
5
6
|
[program:gearman-worker]
command=php /vagrant/tuts-gearman-supervisor/code/worker.php
autostart=true
autorestart=true
numprocs=3
process_name=gearman-worker-%(process_num)s
|
Это скажет Supervisor, что рабочий должен работать в трех процессах и перезапускаться после завершения. Теперь сохраните файл конфигурации, перезагрузите Supervisor и проверьте состояние запущенных процессов:
1
2
3
4
5
6
|
vagrant@localserver:~$ sudo supervisorctl reload
Restarted supervisord
vagrant@localserver:~$ sudo supervisorctl status
gearman-worker:gearman-worker-0 RUNNING pid 4596, uptime 0:01:03
gearman-worker:gearman-worker-1 RUNNING pid 4595, uptime 0:01:03
gearman-worker:gearman-worker-2 RUNNING pid 4597, uptime 0:01:03
|
Мы видим трех рабочих, готовых работать по клиентским сценариям.
Вывод
Мы выполнили основные задачи по установке и настройке Gearman. Теперь вы можете играть с примером кода, поэтому попробуйте внести следующие изменения в код:
- Добавьте некоторый рабочий процесс в фоновом режиме, например, отправив электронное письмо.
- Поиграйте с приоритетами задач используя GearmanClient :: doHigh .
- Блокировка данных с использованием GearmanJob :: sendData , которая может быть полезна в случае длинных задач, которые можно наблюдать в строке состояния.
Кроме того, вы можете масштабировать мощность ваших работников, увеличивая количество процессов или выполняя их на более быстром сервере. И не забудьте использовать Supervisor, чтобы заставить ваших работников работать.
Если у вас есть какие-либо вопросы, не стесняйтесь задавать вопросы в комментариях к статье.
Дальнейшее чтение и ссылки по теме
- Gearman Job Server
- Сервис Gearman на php.net
- Gearman UI для мониторинга задач Gearman
- Супервайзер: система управления процессом