Pull to refresh

Comments 51

есть ли способ вернуть данные назад в очередь в воркере, если они уже были вытянуты? например, для случая когда сервис перевода яндекса лег и апи недоступно, тогда можно было бы вернуть данные в очередь и заснуть на пол часика
Как минимум заново их поместить в очередь
Насколько я помню, достаточно вернуть false из метода-обработчика. Либо из него-же заново добавить задачу в очередь, да.
Вроде бы удаление задачи из очереди должно зависеть от результата ее обработки. Ведь и при запуске сервера можно установить количество повторных выполнений задания при неудаче, и в pecl API есть GearmanJob::sendFail. Но мои практические эксперименты вокруг этого показали, что при любом варианте завершения задачи она удаляется из очереди.
Выходит, что необходимость повторного выполнения надо контролировать самому, и при неудаче самому повторно добавлять задание в очередь на выполнение.
т.е. вернуть false из обработчика недостаточно.
вот в том и вопрос. Правда не знаю насколько идейно в воркере стартовать клиент
Ну если клиент поставил задачу на выполнение в бакграунде, то кроме как из воркера, ее неоткуда повторно вернуть в очередь.
Если же ее выполнения ожидает клиент, то правильнее обрабатывать на клиенте результат выполнения и повторно ставить задачу, поскольку иначе получается уже каша:
— клиент ждет ответа от воркера;
— воркер не может выполнить, добавляет задачу в очередь;
— раз клиент ждет ответа, то тогда и воркер должен ждать ответа по новой задаче, чтобы вернуть его клиенту.
При такой схеме воркер выпадает из обоймы до выполнения задачи, и так можно всех воркеров перелинковать между собой и все повесить.
Для случая, когда
$client->doBackground("taskName", "paramstring");

единственным решением будет:
function func($job) {
    try {
        // work smth
    } catch (Exception $e)
        exit(255);
    }
}

Подсмотрено Найдено тут

PS: а для рестарта воркера можно использовать supervisord.org/ например
Способ именно вернуть забранное таки есть, хотя и не очень красивый. Завершить воркер с кодом отличным от нуля. Т.е. в php просто exit(1); но вот ожидание тогда придется делать как-нибудь еще
Способ есть.

Причем все делается автоматически.
Для этого на стороне воркера необходимо использовать метод GearmanJob::sendFail в случае если невозможно выполнить задачу, в таком случае задача из очереди удалена не будет и сервер снова попробует отдать ее какому — то воркеру.

Количество таких попыток регулируется параметром

-j, --job-retries=RETRIES

при запуске сервера.

Через RETRIES количества безуспешных попыток задача будет удалена из очереди.
Чуть выше мы это обсуждали. Проблема в том, что несмотря на параметр --job-retries использование GearmanJob::sendFail не приводит к возвращению задания в очередь.
Смотрите (код для примера github.com/avorobiev/gearman):
1. запускаем сервер:
$ gearmand -job-retries=2

2. добавляем задание в очередь
$ php client.php

3. проверяем наличие задания в очереди
$ php monitor.php
| function | total | running | workers |
| fail | 1 | 0 | 0 |

4. подключаем воркера
$ php worker.php
Function got: «Function data» and fail

5. проверяем очередь
$ php monitor.php
| function | total | running | workers |
| fail | 0 | 0 | 1 |

ВЫВОД: GearmanJob::sendFail не возвращает задание в очередь. Или я что-то делаю не так?
Возвращает. Но у вас же стоит там while ($worker->work());, так что он снова принимает эту задачу на обработку, ещё раз фейлится и после этого лимит фейлов заканчивается,
Воркер в начале обработки задания выводит ее данные в консоль:
$ php worker.php
Function got: «Function data» and fail < — вот он вывод в консоль

Сколько раз воркер обрабатывал задание можно понять из количества выводов в консоль.
На каждое задание 1 вывод, несмотря на завершение GearmanJob::sendFail. Т.е. повторно задания не обрабатываются.
Похоже, что что — то вы делаете не так, но вот что именно, пока сказать не могу.
Дело в том, что я использовал этот функционал и он работал отлично.
Я на досуге погоняю ваш код и отпишусь.
Спасибо!
Я все это тестировал на gearmand 0.14 + php 5.3.10 (c pecl gearman 0.8.0 + libgearman 0.14)
Если у вас GearmanJob::sendFail будет работать, черканите, на каких версиях ПО.
В моем случае актуально для
PHP 5.3.10 with Suhosin-Patch
gearmand          0.32
pecl gearman     1.0.2
libgearman         0.32
я на сколько понял это просто обёртка для pcntl?
Gearman — это отдельный продукт, который можно также использовать как мост между разными языками программирования. Есть несколько реализаций этого продукта, самая распространённая на Си, наверное.
Я бы дажу чуть в сторону расширил: мост между разной логикой. Клиент и воркер могут быть оба написаны на одном языке, но можно инкапсулировать в клиента — одну логику, в воркера — совсем другую.
Тут очень большое поле для экспериментов. В приведенном примере с переводом я делал по-разному:
— вся обработка в клиенте, воркер только общается с API Яндекса
— вся обработка в воркере, клиент только отправляет задачи и собирает потом куски в кучку

Второй вариант мне субъективно больше понравился.
Спасибо, интересно.

В разделе «Cудьба очереди при рестарте gearman», Вы пишите «и аннулирует регистрацию всех воркеров на сервере. При этом у воркеров сгенерируются исключения вроде «Потеряна связь с сервером».», но если сервер успевает рестартануть между таймаутами воркера, воркер зарегистрируеться на нём ещё раз.

В телнет интерфейсе, также есть полезная команда workers
Если бы вы запустили еще несколько воркеров для перевода, то команда Яндекса бы наверное выслала вам книгу в твердом переплете.

Спасибо за статью, очень познавательно. Не приходилось самому пользоватся Gearman`ом, но теперь вижу несколько вариантов применения для своих сайтов.
Я бы не отказался, но только если в хорошем переводе.
Отвлекаясь от темы: есть несколько переводов Крестного отца Пьюзо на русский. Все, кроме одного — это, как по мне, унылый американский гангстерский боевик. Перевод от Кан — это прекрасная философская книга, которую с удовольствием перечитываешь.

Еще раз сори за офтоп.
Спасибо! Как раз есть подходящая задача.
Все таки Gearman не совсем сервер очередей. Он предназначен именно для удаленного выполнения задач, с чем он справляется очень неплохо.
Интересно, как кто обеспечивает безопасность при использовании Gearman, ведь в нем самом нет средств авторизации… Ничего не мешает подключить к чужому серверу свой воркер, или добавить на чужой сервер задач…
В голову приходит только одно решение — разворачивать между хостами VPN и работать с Gearman строго внутри нее. У кого есть практический опыт — поделитесь!
забиндить на локальный интерфейс?
Точно! Вариант туннелирования локальных портов решение, и гораздо проще VPN.
В этом нет смысла. В таком варианте не будет распределённости. Есть смысл прописывать правила для «своих» адресов.
Почему нет смысла? Если настроить на хосте с воркерами туннель для локального порта 4730 на тот же локальный порт Gearman-сервера, то все заработает. И распределенность будет :-). Вдобавок соединение будет шифроваться ssh.

А вы предлагаете настроить iptables? Тоже вариант, но сложнее в реализации — надо писать правила, и нет шифрования передаваемых данных.
Возможно я не правильно понял mayhem'a. Под биндить на локальный интерфейс, я вижу слушать 127.0.0.1
да, если так, то смысл только в распараллеливании выполнения.
на сайте разработчики пишут, что задача авторизации у них в планах есть, но пока не реализована
На текущий момент, к сожалению, только выруливать внешними средствами, как-то: iptables, vpn etc.
Удивительно, буквально день назад написал аналогичную статью skahin.blogspot.com/2012/04/gearman.html
Только обработка воркеров происходит многопоточным демоном, что позволяет делить большие задачи на части.
Мне кажется, тема Gearman набирает потихоньку обороты.
Хорошая вещь и много применений можно найти, которые сделают жизнь — проще, а код — прозрачнее.
Я вот одного не пойму. Если мне нужно в 100 потоков (к примеру) сайт парсить — я должен 100 воркеров вручную запустить? Понятно что можно скрипт для этого написать, но мне кажется управлять этим не так удобно. Хотелось бы самому указывать количество запущенных воркеров — возможно ли это?
Я вот одного не пойму, скрипт в 10 строке написать сложнее, чем очередной парсер? :)
Ну во-первых есть multi curl ;)
А вообще, у нас в проекте используем supervisord, который прекрасно справляется с управлением процессами воркеров и клиентов gearman'a. Там в конфиге указывается что и как запускать + удобный перезапуск сразу всех воркеров/клиентов
Тут чуть не так.
Воркер — самостоятельный процесс. Как и клиент, как и сам Gearman
Есл Вы хотите всем этим хозяйством управлять согласно Вашему видению и алгоритму — 100 воркеров, 100500 воркеров и т.д., нужна, конечно, общая оболочка

У меня давно зреет мысль попробовать систему, которая сама будет регулировать поведение очереди — запускать/снимать воркеров в зависимости от «нагрузки», сбрасывать задачи о определенным критериям и пр.

Как сделаю — обязательно отпишусь.

Но, возвращаясь к Вашему вопросу — эта система опять же является внешней по отношению и к воркерам, и к клиентам, и к Gearman
Поправка: то, что у вас на второй картинке — это не очереди, это RPC…

В питоне для такого рода задач используют Celery, кстати.
На рисунке действительно не очереди. На рисунке изображено прохождение данных, рисунок просто иллюстрирует изменение логики обработки данных.

Да, конечно, в таком виде это похоже на RPC. Но и на обработку данных в Gearman это тоже похоже. Если туда пририсовать еще одного клиента, все станет на места.
Я постараюсь перерисовать немного яснее.

Спасибо.
Если я правильно понимаю, при использовании Gearman теряются некоторые фишки, предоставляемые IDE.
Например, если подвести курсор к вызову функции, то отобразится подсказка с описанием функции, параметрами, возвращаемым типом…

А при таком синтаксисе ($res = $client->do('function');) эта возможность теряется, так ведь?
Также, как и при любой другой реализации добавления задач в очередь, или, например, при вызове хранимых SQL процедур.
>А при таком синтаксисе ($res = $client->do('function');) эта возможность теряется
Я не понял, что тут теряется? Подсказка для метода do? Не должна она тут теряться.
Да, на тему function IDE Вам ничего не подскажет.
Но
Аргумент у function — всегда один и всегда string: это сериализованные данные или просто string
Возвращает она тоже string: сериализованные данные ну или опять же просто string

Так что Вы правы: при работе с Gearman учет того:

— что делает каждая ф-я
— что ей потребуется после операции unserialize (внутри ф-и)
— что получится после unserialize того, что она вернет

нужно где-то вести, IDE вам тут ничего не подскажет.
Большое спасибо.
Можно ставить через pecl только нужно обновить python.

sudo apt-get install python-software-properties -y
sudo add-apt-repository ppa:gearman-developers/ppa 
sudo apt-get update
sudo apt-get install gearman-job-server libgearman-dev gearman-tools php-pear php5-dev -y
sudo apt-get install libevent-dev uuid-dev -y
pecl install gearman

Оригинальная статья: http://rdstash.blogspot.com/2012/02/installing-gearman-101-on-ubuntu-1104.html
Я заказал компиляцию pecl-расширения php_gearman.dll под Денвер (php 5.3.13) и готов поделиться ею с сообществом! :)

PECL-расширение версии 1.1.0 (от 2012-09-22), библиотека libgearman использовалась версии 0.41.

Скачать и протестировать можно по одной из ссылок: Зеркало 1, Зеркало 2, Зеркало 3

Пока найден только один баг — большие объемы данных нельзя передать между клиентом и воркером.
Подскажите, пожалуйста, gearman не хочет обновлять код который указан в job. Т.е берем job. Запускаем код. Job пишет в лог, и видно что она работает. Когда сервер остановлен то видно что не работает. При этом изменения в коде никак не влияют на поведение.

/etc/init.d/gearman-job-server force-reload такая команда не помогает, остановка и запуск очереди также ничего не дает.

Подскажите, в чем может быть причина, куда копать?
Sign up to leave a comment.

Articles