Сервер черг Gearman: досвід практичного використання і веб-додаток Gearman Monitor && Control

Сервер черг 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: з БД формуємо завдання — зміна цін, додавання, зупинка, видалення. Далі завдання кидаються на сервер черг, і там спокійно обробляються в кілька потоків: воркеры звертаються до AdWords API або API Яндекс.Директ і виконують необхідні операції.
Вийшло ось так:

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 вирішує дві задачі: паралельне отримання і обробка даних, і відображення процесу у реальному часі.
Ось клієнтський інтерфейс системи.


4) Постачальники готельних послуг надають дані. Завдання: відобразити готелю на карті. Завдання начебто зовсім проста, так як дані надаються разом з координатами. Але, на жаль, багато з наданих координат невірні, і клієнтам показувати таке не можна — адресу в одному місці, а маркер готелю — зовсім в іншому. Було прийнято рішення самостійно отримувати дані за допомогою геокодера Гугла, використовуючи адреси готелів. Але при простому виклик геокодера в яваскрипте багато маркери не відображаються — яваскрипт намагається одночасно отримати адреси всіх готелів, геокодер блокує більшість запитів з-за перевищення ліміту на кількість звернень в секунду.
Рішення: всі запити геокодера з яваскрипт направляються на свій проксі, які передає завдання на сервер черг.
Тут Gearman вирішує завдання регулювання і обмеження доступу до зовнішнього ресурсу — API геокодера Гугла.


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

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

Уявімо, що ми працюємо з сервером черг. Як запустити один воркер? Набираємо в консолі
php worker.php

Ок, потрібно запустити 20 воркеров для паралельної обробки. Відкрити 20 консолей? Не варіант. Чи потрібно запустити кілька різних воркеров — та ж проблема. Отже, потрібно метод класу і реалізація в веб-інтерфейсі:
— запуск воркеров, з вибором якого саме і зазначенням кількості
Ок, розробляємо далі, запустили воркер, він працює. А зупинити його як? Обов'язково потрібна
— зупинка воркеров
Ситуація: запустили кілька різних воркеров в процесі розробки, і — ой, стоп, все тому, параметр не той! Нас виручить:
— зупинка всіх воркеров однією дією
Але воркер — він як маленька дитина: робить чогось, а що — неясно, за ним догляд потрібен. Для цього потрібно:
— логування роботи воркера
Тут трохи детальніше. Дуже приємно бачити, що робить воркер, насолоджуватися творінням. Але ось ситуація: бац — і воркер вилетів. Або ще краще — взагалі не стартує. А що за помилка? У коді неправильно, або необроблене виняток, або помилку від зовнішнього сервісу не передбачили? Тому:
— логування помилок воркера, включаючи фатальні
Лог може бути великим, перегляд його стомлює, а часто неможливий із-за об'єму. потрібно
— пошук в балці довільного тексту
З воркерами розібралися, вони нам підвладні. А чергу?
Знову ж таки, воркеры — як маленькі діти, розбирають купку, а що в тій купці? Тому:
— виведення всіх функцій, які зареєстровані на сервері черг
— висновок черги завдань по кожній функції
Але клієнти накидали на сервер черг завдань, по одній накопичилося їх 1000, а воркер — один і явно не впорається, або взагалі немає воркеров і не передбачається. Або ближче до життя: зовнішній сервіс, до якого зверталися воркеры, недоступний чергу потрібно скидати. Як бути? Потрібно
— скидання/очищення черги по кожній функції
Але ось ми награлися Gearman, потрібно відключатися. Або ж ми щось зробили не так, відправили на сервер черг, і потрібно терміново зупинити всі. Допоможе
— повний скидання: очищення всі черги, зупинка всіх воркеров.

Додамо, що все, що відбувається повинно відображатися в реальному часі без будь-яких оновлень сторінки.

Усі зазначені вище завдання вирішить клас Gearman_Monitor і веб додаток Gearman Monitor && Control, яка реалізує методи цього класу.
Проект Gearman Monitor && Control на Github
Чистий скріншот веб-додатки
Той же скріншот з докладними поясненнями

Ось відео роботи веб-додатки


Для використання в розробці потрібні класи 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, і швидко на коліні допиливалась сама перша версія. В результаті вона і опублікована як багаторазово перевірена, надійна, стійка і зручна.

Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.