Статьи

Нежное введение в Gearman и его концепции

Gearman (анаграмма «Менеджер») — это система для распределения рабочих единиц на нескольких разных серверах (или нескольких процессах на одном сервере), позволяющая вызывающему коду делать что-то совершенно другое во время выполнения задачи. Gearman не предназначен для межпроцессного взаимодействия, но является способом сообщить другим процессам, что есть доступная работа, и позволить этим процессам (называемым рабочими) взять часть работы для себя.

Одна из общих тем, которая появляется на IRC-канале gearman на freenode, — это попытка понять, что такое gearman и как все сочетается. Я попытаюсь объяснить различные концепции и каковы различные обязанности инфраструктуры рабочего механизма. На веб-сайте Gearman также есть руководство « Приступая к работе » с небольшим количеством примера кода и инструкций по установке, так что вы можете оставить его открытым на другой вкладке. Итак, начнем: простое учебное пособие, объясняющее концепции, а не просто пример кода.

Есть три основных компонента установки редуктора. Это клиент (кто-то запрашивает выполнение задачи), работник (кто-то выполняет задачу) и сервер (который координирует задачи между клиентами и работниками). Все эти три компонента должны быть запущены, чтобы вы могли использовать что-то полезное с помощью gearman. Стоит отметить, что я буду использовать имя «задача» для выполнения отдельного элемента, вы также увидите эту названную «функцию» (то есть имя фактической функции, которую задача выполняет, — сервер предлагает несколько «Функции», которые клиент может вызвать). Некоторые API могут также ссылаться на «задачу» как на набор функций, которые должны быть вызваны. Я буду использовать первое определение; задача — это вызов функции на сервере вместе с данными для задачи и идентификатором задачи. Несколько последующих задач будут вызывать одну и ту же функцию.

Я расскажу немного подробнее о каждом из этих компонентов, но важно, чтобы вы сначала поняли, как все взаимосвязано. Обмен сообщениями между различными частями может быть проиллюстрирован следующим образом:

client -> server: ask server to perform a task
server acknowledges request and assigns an identificator to the request
server -> all workers: tell workers registered for the task that there is work to be performed
worker -> server: I'll perform the task you just told us about
server -> worker: ok, go ahead, here's the information about the task.
worker -> server: here's the result of the task performed
server -> client: here's the result of the task you asked me to get someone to do for you

Идея, стоящая за сервером и сообщающая всем работникам, что есть доступная работа, состоит в том, чтобы позволить работнику, который быстрее всего отвечает, фактически получить задачу, поскольку предполагается, что это работник с наименьшей нагрузкой на сервере, на котором он работает (так как он отвечает быстро, сервер не занят другими делами). Как я писал выше, работник — это часть кода, которая фактически выполняет свою работу — работник выполняет задачу, которую клиент отправил на сервер gearman.

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

Клиент Gearman

В Gearman клиент — это фрагмент кода, который подключается к серверу и запрашивает выполнение задачи. Это может быть динамическая веб-страница (работающая на python, ruby, PHP, perl или другом языке с подходящей библиотекой Gearman), полностью приложение, которое подключается к Gearman, работнику (для отправки новой задачи или для разделения текущей задачи на несколько меньших задач, которые должны быть выполнены другими работниками) или сочетание вышеперечисленного. Важно то, что это просто клиент — у него есть задача, которую нужно выполнить, и он попросит сервер Gearman найти кого-то, кто может выполнить задачу.

Клиент может работать в синхронном (блокирующем) или асинхронном (неблокирующем) режиме. Первый заставит клиента ждать, пока задача не будет выполнена работником (и если работника нет, он будет ждать неопределенно или до достижения тайм-аута в клиенте), в то время как последний просто вызовет и забудет задание на сервер Gearman (сервер подтвердит, что задание получено), а затем продолжит свой веселый путь. Сервер Gearman предоставит значение идентификации задачи, которое асинхронный клиент может использовать для запроса текущего состояния задачи, которую он просил выполнить (при условии, что фактический работник предоставляет такие обновления).

Небольшой пример того, как может работать клиент (с использованием PHP):

    <?php
    $client = new GearmanClient();
    $client->addServer('localhost', 4730);

    $arguments = array(
        'url' => 'http://www.example.com/',
    );

    $client->addTaskBackground('fetchURL', json_encode($arguments));

    $client->runTasks();

 

Это отправит запрос серверу Gearman, работающему на той же машине, что и скрипт, с запросом на выполнение функции «fetchURL» и включив в него массив аргументов (вы могли бы просто включить только URL, но я нахожу что этот путь будет легче расширять в будущем — и использование JSON для обмена данными делает рабочий код более независимым от языка программирования). Этот код использует addTaskBackground для отправки задачи, которая будет выполняться асинхронно. Мы не заинтересованы в результате этой задачи в данном конкретном фрагменте кода — рабочий либо предоставит результат другими способами (сохранит его в базе данных, в memcache, вызовет функцию API, сообщающую нам, что она завершена), либо, возможно, нас совсем не интересует результат, просто мы пытались выполнить задачу. Если вы используете синхронный интерфейс,данные, возвращенные работником, будут возвращены в ваш код как возвращаемое значение от клиента.

Как видите, код клиента очень и очень прост. Здесь не выполняется никакой реальной работы, мы просто сообщаем серверу, что хотели бы, чтобы за нас была выполнена какая-то работа.

Рабочий Gearman

Рабочий Gearman — это место, где выполняется вся фактическая работа (кто бы мог догадаться). Это приложение, которое получает уведомление о том, что оно должно проснуться и выполнить небольшую тяжелую работу, и которое фактически выходит из строя и делает именно это. Какую работу он выполняет, зависит от того, для чего вы используете Gearman, но есть пара вариантов использования: изменение размера изображения до меньших размеров (например, миниатюр), преобразование загруженного видео в другой формат для конкретного устройства, отправка уведомлений по электронной почте, обновление внутренней поисковой системы, такой как Solr, и ряд других задач. Пока задача не важна для продолжения работы приложения (не нужно ждать доставки электронного письма, если вы собираетесь показать сообщение «Ваша информация была сохранена»), затем Gearman (и другие альтернативные очереди сообщений) является допустимым решением.

Вы будете запускать каждого работника как отдельный процесс. Работник может выполнять несколько различных функций (хотя вы должны (обычно) держаться подальше от многопоточности, чтобы выполнять их одновременно). Это означает запуск нескольких копий одного и того же работника, если вы хотите разрешить нескольким работникам выполнять задачу одновременно (т. Е. Если вы хотите отправить 30 электронных писем параллельно), вы будете запускать каждого работника как отдельный процессы (30 работников в этом случае). Существует несколько демонов и платформ, которые могут помочь вам управлять количеством доступных процессов в зависимости от нагрузки на сервер и задачу, например supervisord и GearmanManager (демон PHP). Другое возможное решение — использовать экран запустить несколько рабочих, что также позволит вам в любой момент присоединиться к выходу любого работника.

Как работник выполняет свою работу, зависит от самого работника. В большинстве случаев вам придется написать немного кода, чтобы представить ваш код как функцию Gearman (чтобы клиенты могли отправлять задачи для выполнения этой функции), но этот код обычно просто создает экземпляр рабочей среды из библиотеки Gearman, которую вы ‘ их использование, позволяя вам регистрировать, какие функции вы сможете выполнять, и прикреплять обратные вызовы, сообщающие библиотеке, какую часть вашего собственного кода следует вызывать при поступлении запроса на выполнение задачи.

Простой пример, измененный из руководства по началу работы с Gearman:

<?php
$worker = new GearmanWorker();
$worker->addServer("localhost", 4730);
$worker->addFunction("fetchURL", "fetch_url");

while ($worker->work());

function fetch_url($job)
{
    $arguments = json_decode($job->workload());

    if (!empty($arguments['url']))
    {
        print("Fetching " . $arguments['url'] . "\n");
        return file_get_contents($arguments['url']);

$ Рабоче> работа () вызов метода будет ждать , пока работа не приходит, а затем выполнить обратный вызов , как это определено в вызове AddFunction. addFunction инструктирует работника сообщить серверу Gearman, что этот работник может выполнять любые задачи, вызывающие функцию «fetchURL». Обратный вызов, предоставленный библиотеке («вызовите эту функцию PHP (« fetch_url »), когда задачи хотят вызвать« fetchURL »»), получит объект задания, содержащий информацию о задании (задании), которое нужно выполнить. Метод workload () возвращает рабочую нагрузку — информацию, которую мы включили в дополнение к какой функции вызывать в примере клиента. Сервер получает рабочую нагрузку от клиента, а затем отправляет ее работнику вместе с информацией о задаче.

Поскольку наш клиент вызывает сервер с помощью асинхронного интерфейса, он не будет ждать, пока работник вернет содержимое веб-страницы, а будет использовать -> do () или один из других методов переднего плана в библиотеке PHP Gearman.

Сервер Gearman

Обычно используется Gearman Server C-версии сервера. Существует также версия PERL, но в настоящее время активно разрабатывается сервер C. О сервере мало что можно сказать, обычно вы просто запускаете его и позволяете ему работать самостоятельно, делая то, что он должен был делать все время.

У меня есть одно простое предложение, если вы впервые играете с Gearman: запустите сервер с опцией -vvv. Это сделает gearmand намного шумнее и позволит вам увидеть, как клиенты регистрируются на сервере, проверяют связь с сервером и получают немного больше информации о том, что происходит внутри серверного процесса.

Вы также захотите указать IP-адрес, с которым должен связываться сервер gearman — по умолчанию он связывается со всеми интерфейсами, а так как gearmand не имеет встроенной аутентификации по умолчанию, вы не хотите предоставлять свой сервер весь мир.

Вот пример того, как мы запускаем gearmand на одном из наших серверов:

screen -d -m -S gearmand /usr/local/sbin/gearmand -L 127.0.0.1 -p 4730 -vvv

Вы можете удалить часть, относящуюся к экрану, если вы просто хотите играть с gearmand:

/usr/local/sbin/gearmand -L 127.0.0.1 -p 4730 -vvv

 

Если у вас есть gearmand на вашем пути, а не в том же месте, что и у нас, удалите / usr / local / sbin 🙂 Это свяжет gearmand с вашим локальным хостом и будет использовать порт по умолчанию (ранее порт по умолчанию отличался от 4730, поэтому мы предоставляем это на всякий случай).

Делать все это вместе

Самый простой способ поэкспериментировать с gearman — это просто открыть три окна терминала: одно для gearmand с включенной регистрацией, одно для вашего работника и его выходных данных и последнее окно для клиента, отправляющего запрос задачи в gearmand (вы можете использовать ‘ двоичный файл gearman для этого, просто обязательно включите любые данные в соответствующем формате). Когда вы отправляете задачу для функции, зарегистрированной работником, вы должны увидеть, как она подняла ее, а затем начать обработку задачи как можно скорее. Через некоторое время (в зависимости от того, как вы реализовали своего работника и какую функцию он выполняет), результат должен появиться в вашем клиенте.

Наши производственные установки обычно используют веб-приложение (PHP или python / django) в качестве клиента в приведенном выше сценарии. Эти функции, как правило, являются долго выполняющимися задачами, такими как анализ путей GPS, кодирование видео и загрузка файлов или внутренняя аналитика веб-сайта (где мы просто хотим регистрировать вещи, а не ждать завершения самой регистрации). Веб-приложение отправляет запрос на gearmand, как только файл получен, с полезной нагрузкой пути к файлу, который нужно обработать. Рабочие выполняют свою функцию и затем сохраняют информацию обратно в базу данных или на диск, затем обычно вызывают веб-службу, чтобы сообщить веб-приложению, что работа выполнена, и любое внутреннее состояние может быть обновлено, чтобы включить (и показать) результат задачи.

Очереди сообщений (такие как Gearman) стали одной из основных технологий, стоящих за многими современными веб-приложениями (и не-веб-приложениями в этом отношении), поэтому на самом деле нет оснований избегать хотя бы небольшого перебора с этим и добавления еще одного возможного инструмента. к вашим будущим вариантам.