Сервер очередей Gearman: опыт практического использования и веб-приложение Gearman Monitor && Control

в 6:29, , рубрики: gearman, gearman monitor, gearman monitor control, php, Программирование, Разработка веб-сайтов

Сервер очередей Gearman — прекрасный инструмент. Но в работе сервер очередей в чем-то напоминает системный блок: что-то делает, но для того чтобы знать, что именно, и управлять процессом, нужен монитор с клавиатурой, и представление о том, что вообще происходит в системном блоке.
Зачастую кажется, что Gearman — как диковинный инструмент без рукоятки: интересен и красив, но неясно, зачем нужен, а пользоваться болезненно.
Нужно выбраться из этой ситуации, Gearman действительно хорош.
Давайте рассмотрим:

  • Gearman «на пальцах»
  • примеры реальных задач с использованием Gearman
  • веб-приложение и класс для мониторинга в реальном времени и управления процессами на сервере очередей Gearman

Интересно? Прошу под кат.

Можно ли объяснить принцип работы Gearman «на пальцах»?

Можно.

Что такое воркер?
Это просто консольный скрипт, на каком языке программирования — неважно. Скрипт запущен постоянно, это демон.
При запуске воркер-демон отправляет на сервер строки — имена функций, которые он может выполнить, открывает сокет на сервер и ждет.

Какие данные получает воркер?
Воркеру приходит две строки: первая — имя ф-и, которую нужно выполнить, и вторая — аргумент. Подчеркнем: воркеру нельзя передать несколько аргументов, массив, объект — только строка, все другие виды данных должны быть приведены к строке — сериализация или json.
Собственно, что удивительного — вся передача данных по протоколу, например, HTTP — это тоже передача только строк.

Откуда приходят строки — задания для воркера?
Клиент Gearman, отправляя на сервер задачу, передает как раз две строки — имя функции, которую нужно выполнить, и аргумент в виде строки. При этом задача в очереди помечается как находящаяся в процессе выполнения.

И что дальше?
Если задача — фоновая, воркер выполняет функцию и передает на сервер только сигнал выполнения ф-и. Если задача — не фоновая, воркер передает Gearman строку — результат выполнения ф-и, и сигнал выполнения.
При получении сигнала выполнения Gearman отмечает задачу как выполненную и удаляет ее из очереди.

А если в процессе выполнения функции воркер аварийно завершит работу или в ф-и возникнет нештатная ситуация — то есть ф-я не выполнится?
Gearman в этом случае не получит сигнала успешного завершения, и задача останется в очереди

Что такое клиент?
Отдельное понятие «клиент» для Gearman сложно выделить. Можно обращаться к Gearman из ЯП, отправляя и принимая данные — можно отправить и ждать, можно в фоновом режиме. Но все еще проще.

«Получает», «отправляет», «приходят» — как происходит обмен данными с сервером? Нужны низкоуровневые дополнения в ЯП?
Общение с Gearman происходит через сокеты. Можно вообще не иметь дополнений в ЯП для работы с Gearman, обойтись работой с сокетами и Telnet. Так, например, в PHP работать с Gearman можно, установив PECL дополнение в язык, а можно использовать Pear библиотеку, просто подключив файлы нескольких классов.

Если клиент отправит на сервер задачу, а воркера нет для этой функции нет — или нет свободного, или нет вообще?
Задача «повиснет» в ожидании воркера. Если придут еще задачи на эту же функцию, образуется очередь — Gearman сервер очередей все же.

Можно ли на сервере очередей различить две задачи на одинаковую функцию?
Нет. Ни по аргументу, никак.

Можно ли узнать, какая в очереди отправленная задача?
Поскольку задачи на одну и ту же ф-ю неразличимы, то нет.

Можно ли узнать, сколько задач в очереди?
Да. Можно также узнать, сколько воркеров может обработать эту задачу, и откуда эти воркеры (IP).

Представим, что поступила одна задача, и ее могут выполнить несколько воркеров. Кому достается задача?
Задачи неразличимы, но и воркеры тоже неразличимы. Какому именно воркеру Gearman отдаст задачу — так просто не ответить. Очереди воркеров нет.

Какие виды задач бывают на сервере очередей?
Задачи можно разделить 1) по приоритетам, 2) фоновая задача или нет
1) Приоритетов три — обычный, low — менее приоритетный, чем обычный, и high — более высокого, чем обычный, приоритета. Приоритет учитывается в очереди, по умолчанию — обычный приоритет.
2) Фоновая задача ничего не отдает серверу очередей, и клиент не получает никаких данных. Обычная задача должна вернуть строку, и Gearman отдаст эту строку клиенту как результат выполнения задачи.

Сколько можно одновременно запустить воркеров?
Тут нужно уточнить — не сколько запустить, а сколько воркеров может одновременно подключиться к Gearman для обработки задач.
Теоретически — сколько угодно. В реальности максимальное числов воркеров может быть ограничено максимальным числом одновременных потоков на внешний ресурс, числом одновременных подключений к БД и прочими условиями, не зависящими от Gearman. Автору этих строк удавалось запустить около 1000 на одном сервере, далее начинала ругаться MySQL.

Можно ли работать в PHP с Gearman на Windows?
Вопрос разделяется на два: 1) можно ли запустить сам сервер очередей Gearman на Windows и 2) можно ли работать с уже имеющимся на внешнием хосте сервером очередей.
1) есть вариант установки Gearman на Windows с использованием cygwin

2) Для комфортной работы, для использования в коде привычных конструкций вида

$worker = new GearmanWorker();
$worker->addServer()

и подобных требуются дополнения в язык. Это сразу накладывает ограничения: вы не только не можете это сделать под Windows, но и не сможете это сделать на хостинге, если у вас нет прав на доступ к серверу, позволяющих устанавливать пакеты.
Denwer и OpenServer не содержат дополнений для работы с Gearman.
Значит, выхода нет, Gearman — только для *nix систем?
Нет конечно. Решение проблемы — подключение к проекту библиотеки Pear Net_Gearman
Там другие названия классов и немного другая логика, но пережить это можно и работать с Gearman позволяет полноценно.

Реальные задачи с использованием Gearman

1) Рекламное агентство сопровождает рекламные кампании AdWords и Яндекс.Директ для средних и крупных интернет-магазинов. Информация о товарах меняется постоянно: меняются цены (курс доллара и пр.), появляются новые товары, некоторые товары заканчиваются на складе, некоторые снимаются с продажи. Товаров в каждом магазине тысячи и десятки тысяч.
Задача: сделать так, чтобы информация в рекламе AdWords и Яндекс.Директ была актуальной: нужно менять цены, добавлять рекламные объявления/группы/кампании для новых товаров, останавливать рекламу для закончившихся на складе, удалять объявления для товаров, снятых с продажи.
Задача просто решается с использованием Gearman: из БД формируем задачи — изменение цен, добавление, остановка, удаление. Далее задачи бросаются на сервер очередей, и там спокойно обрабатываются в несколько потоков: воркеры обращаются к API AdWords или API Яндекс.Директ и выполняют требуемые операции.
Получилось вот так:
Сервер очередей Gearman: опыт практического использования и веб-приложение Gearman Monitor && Control - 1
Gearman здесь решает две задачи: параллельное выполнение процессов — раз, и регулирование доступа к внешним ресурсам.
Ни AdWords API, ни Яндекс.Директ API не дадут вам выполнять операции в сто, например, потоков — есть ограничение на количество запросов в секунду. В моем случае получилось максимум 4 потока к AdWords API и 8 потоков к Яндекс.Директ API.
О времени выполнения. Начальная загрузка 10к товаров занимает до несколько часов, создается несколько сотен тысяч объявлений, несколько сотен кампаний и пр. Обновление — несколько минут, полностью в автоматическом режиме.

2) Продолжение задачи 1. Почти все магазины передают данные в виде XML-файла. Но некоторые присылают XLS-файл. Нет проблемы получить данные из XLS-файла, есть PHPExcel. Но у PHPExcel есть нюанс: при обработке больших файлов он сильно тормозит, но главное — потребляет память вплоть до превышения лимитов в php.ini 1024Мб и больше.
Процесс обработки файла XLS с помощью PHPExcel может быть распараллелен (идея была почерпнута из вот этой публикации, спасибо MParshin). Воркеры читают файл по строкам, каждый воркер — свои строки, таким образом, процесс распараллеливается.
Здесь Gearman решает две задачи: 1)параллельная обработка и 2)обход ограничения на лимит памяти одного PHP-скрипта.
Разумеется, в этом случае тоже нельзя запустить тысячу, например, воркеров — память сервера тоже не бесконечна. В моем случае получалось обрабатывать XLS-файл в 20 потоков.

3) Крупный вендор — производитель оборудования — хочет знать, по каким ценам реально торгуется его оборудование. Данные можно получить из каталога, но опять же — только с сайта. Процесс стандартный: парсер, воркеры в несколько потоков получают данные с сайта каталога.
Наличие API в разработанной системе Gearman Monitor && Control позволяет демонстрировать клиенту — вендору — получение данных в реальном времени.
Здесь Gearman решает две задачи: параллельное получение и обработка данных, и отображение процесса в реальном времени.
Вот клиентский интерфейс системы.
Сервер очередей Gearman: опыт практического использования и веб-приложение Gearman Monitor && Control - 2

4) Поставщики гостиничных услуг предоставляют данные. Задача: отобразить гостиницы на карте. Задача вроде бы совсем простая, так как данные предоставляются вместе с координатами. Но, к сожалению, многие из предоставленных координат неверные, и клиентам показывать такое нельзя — адрес в одном месте, а маркер гостиницы — совсем в другом. Было принято решение самостоятельно получать данные с помощью геокодера Гугла, используя адреса гостиниц. Но при простом вызове геокодера в яваскрипте многие маркеры не отображаются — яваскрипт пытается одновременно получить адреса всех гостиниц, геокодер блокирует большинство запросов из-за превышения лимита на число обращений в секунду.
Решение: все запросы геокодера из яваскрипта направляются на свой прокси, которые передает задачу на сервер очередей.
Здесь Gearman решает задачу регулирования и ограничения доступа к внешнему ресурсу — API геокодера Гугла.
Сервер очередей Gearman: опыт практического использования и веб-приложение Gearman Monitor && Control - 3

5) Последний пример — комплексное использование сервера очередей. На сайте предоставлена специфическая информация о нескольких тысячах объектов. Задача: получить и перевести эту информацию. Решение: запускаем воркеры для получения информации, и воркеры для перевода. Первые воркеры в несколько потоков получают информацию, как только воркер получил требуемый текст, он опять ставит задачу на сервер очередей, задачу для воркеров перевода. Воркеры-переводчики переводят ее и кладут уже готовый материал в БД.
Gearman здесь используется стандартно — получение и обработка информации в несколько потоков, нюанс только в том, что воркеры сами ставят задачи другим воркерам.

На основе практических задач появились требования к системе управления Gearman

Представим, что мы работаем с сервером очередей. Как запустить один воркер? Набираем в консоли php worker.php
Ок, нужно запустить 20 воркеров для параллельной обработки. Открыть 20 консолей? Не вариант. Или нужно запустить несколько разных воркеров — та же проблема. Итак, требуется метод класса и реализация в веб-интерфейсе:
— запуск воркеров, с выбором какого именно и указанием количества
Ок, разрабатываем дальше, запустили воркер, он работает. А остановить его как? Обязательно нужна
— остановка воркеров
Ситуация: запустили несколько разных воркеров в процессе разработки, и — ой, стоп, все назад, параметр не тот! Нас выручит:
— остановка всех воркеров одним действием
Но воркер — он как маленький ребенок: делает чего-то, а что — неясно, за ним присмотр нужен. Для этого потребуется:
— логирование работы воркера
Тут чуть подробнее. Очень приятно видеть, что делает воркер, наслаждаться творением. Но вот ситуация: бац — и воркер вылетел. Или еще лучше — вообще не стартует. А что за ошибка? В коде неправильно, или исключение необработанное, или ошибку от внешнего сервиса не предусмотрели? Поэтому:
— логирование ошибок воркера, включая фатальные
Лог может быть большим, просмотр его утомителен, а зачастую невозможен из-за объема. требуется
— поиск в логе произвольного текста
С воркерами разобрались, они нам подвластны. А очередь?
Опять же, воркеры — как маленькие дети, разбирают кучку, а что в той кучке? Поэтому:
— вывод всех функций, которые зарегистрированы на сервере очередей
— вывод очереди задач по каждой функции
Но вот клиенты набросали на сервер очередей задач, по одной скопилось их 1000, а воркер — один и явно не справится, или вообще нет воркеров и не предвидится. Или ближе к жизни: внешний сервис, к которому обращались воркеры, недоступен, очередь нужно сбрасывать. Как быть? Требуется
— сброс/очистка очереди по каждой функции
Но вот мы наигрались Gearman, нужно отключаться. Или же мы что-то сделали не так, отправили на сервер очередей, и нужно срочно все остановить. Поможет
— полный сброс: очистка все очереди, останов всех воркеров.

Добавим, что все происходящее должно отображаться в реальном времени без всяких обновлений страницы.

Все указанные выше задачи решит класс Gearman_Monitor и веб приложение Gearman Monitor && Control, реализующее методы этого класса.
Проект Gearman Monitor && Control на Github

Чистый скриншот веб-приложения

Сервер очередей Gearman: опыт практического использования и веб-приложение Gearman Monitor && Control - 4

Тот же скриншот с подробными пояснениями

Сервер очередей Gearman: опыт практического использования и веб-приложение Gearman Monitor && Control - 5

Вот видео работы веб-приложения

Для использования в разработке требуются классы Gearman_Monitor и Gmonitor_Settings (имена php-файлов совпадают с именами классов).
Свойства и методы классов подробно задокументированы в самих файлах. Поясним только вот это:

public static $func_name_synonyms = array(
        'summ' => 'Sum',
        'muliply' => 'Умножение и деление в воркере',
        'subtract' => 'Substract Function',
        'divide' => '功能',
    );

Здесь
ключ массива — имя функции, зарегистрированное воркером на сервере очередей
значение — То, что вы увидите в таблице, в любом виде. Это для удобства работы операторов — раз, и еще применение. Представим, что на одном сервере очередей «крутятся» несколько проектов. Разумеется, хочется видеть не все в куче, а только свой проект. Для этого указываем синонимы (если не указали, используется имя функции), и устанавливаем значение

public static $synonyms_only_view = true;

В этом случае в таблице функций будут отображаться только те, для которых есть синонимы.

Еще один момент. Веб-приложение содержит логгер и обработчик ошибок PHP. Если вы подключите к воркеру файл gearman_includes.php, то сможете записывать из воркера в лог, который отображается, и ошибки воркера тоже будут записываться и отображаться в логе.

В директории /workers лежит два воркера. fake_worker.php нужен для работы приложения, второй воркер — из работающего проекта, можно рассмотреть его как пример.

Для использования веб-приложения потребуется:
— создание в БД таблицы log (см. файл log_create.sql)
— указать параметры соединения с БД в файле Gearman_Db.php
— установить права на запись во все директории внутри view / Smarty / smarty_dirs (в первую очередь касается директории view / Smarty / smarty_dirs / templates_c )
— указать хост сервера Gearman в файле Gearman_Monitor.php

Всем удачных очередей!

P.S. Веб-приложение выдрано из работающего проекта, могут быть небольшие нестыковки, заранее прошу прощения.
Еще момент. Неоднократно делались попытки переписать веб-приложение — облагородить код, интерфейс, но постоянно возникали задачи с использованием Gearman, и быстро на коленке допиливалась самая первая версия. В результате она и опубликована как многократно проверенная, надежная, устойчивая и удобная.

Автор: konst20

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js