Pull to refresh

Gearman – фреймворк для распределения задач, введение

Server optimization *
Sandbox


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

    В любом достаточно сложном с точки зрения функциональности и нагруженности проекте рано или поздно встаёт вопрос оптимизации и масштабируемости. Известно множество подходов к решению данного комплекса задач, начиная от банального увеличения вычислительной мощности всей системы или особо нагруженных её частей, и заканчивая комплексными решениями в виде специализированных программно-аппаратных комплексов. Объединяет данные решения не только цель — быстрее, выше, сильнее, но и подход к их решению — поиск и определение слабых мест. Зачастую bottleneck это ресурсоёмкая задача связанная с обработкой графической информации, шифрованием, архивированием, тяжёлыми запросами к базе, обрабатывающими и/или возвращающими большой объём информации.

    Gearman — проект с открытым исходным кодом, который был разработан парнями из Danga Interactive. Название является не чем иным, как анаграммой к слову manager, и именно роль менеджера и является кратким описанием функциональности данного приложения — управление, контроль и распределение различных задач. Первоначально gearman был реализован на Perl, но со временем был переписан на C с использованием библиотеки libevent, наличие которой является необходим для функционирования основной части — сервера задач. Установка для любой *nix системы не представляет собой больших трудностей, а в большинстве дистрибутивов linux – пакет gearman входит в стандартный репозиторий.

    Здесь стоит объяснить почему автор употребил слово «фреймворк» в заголовке данной статьи. Дело в том, что использование gearman хоть и является относительно простым, в тоже время эффективное решение поставленной задачи потребует достаточно серьёзной разработки — это не готовое решение.

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

    Клиент и исполнитель используют Gearman API для вызова и реализации необходимых функций. Схема, которая иллюстрирует вышеописанную архитектуру, приведена на основном сайте проекта:

image

    Рассмотрим классический пример работы такой системы — пользователь закачал фотографию на сайт, и хочет показать её всем своим друзьям. Необходимо быстро подготовить различные размеры данной фотографии, для использования по всему сайту. Да, до определённого момента все работы по генерации графики можно проводить в основном коде системы, а потом придёт хабраэффект, и вся система рухнет под наплывом желающих. Теперь рассмотрим как эту задачу можно решить с использованием Gearman — при получении фотографии, мы создаём задачу для gearman сервера, в которую входит необходимая информация о фотографии (в принципе возможно включить в задачу даже саму фотографию, но, мне кажется, это будет накладно, лучше использовать адрес) и отправляем её на выполнение. Сервер задач выбирает (round robin) свободного исполнителя (как Вы наверное уже догадались, исполнителей может быть несколько) и отсылает задачу на выполнение. Исполнитель получает всю необходимую информацию, обрабатывает её как нам бы этого и хотелось — и отправляет ответ об успешно выполненной задаче и, если задача была синхронная, результат работы. Да, задачи бывают двух типов — синхронные, когда клиент ждёт выполнения отправленной задачи, и соответственно результат, и асинхронные, когда клиент выступает только в роли инициатора задачи. Теперь добавляем сюда факт, что протокол общения между частями gearman приложения — TCP/IP, то есть подразумевается, что каждая часть (сервер, клиент, исполнитель) может находится на отдельной машине. Серверов и клиентов может быть несколько. Реализация клиента и исполнителя не зависят друг от друга (доступные языки в которых имплементирован API для работы с gearman включают в себя perl, php, python, java, C, MySQL UDF и др.). Проект активно развивается — новые версии с исправлением ошибок и улучшениями выходят каждый месяц. На выходе получаем довольно радужную картину, где спектр решаемых задач ограничен только фантазией и опытом разработчика. Для примера, несколько общих задач, которые успешно решались и решаются с использованием gearman:
  • вышеописанная задача с обработкой фотографии, причём не стоит ограничиваться только генерацией различных размеров
  • асинхронная инвалидация/обновление данных в кэше, без использования крона и задержек со стороны клиента
  • архивирование больших объёмов данных
  • работа с данными в формате — (ключ => значение), с использованием шифрования на стороне исполнителя

    Теперь немного практической информации. Основным объектом работы в gearman является задача — task, которая состоит из типа (синхронный, асинхронный), названия задачи (к примеру resize), и параметров — workload. Каждая задача идентифицируется по паре название/параметры. То есть если на сервер поступит две одинаковые задачи с одинаковыми параметрами, выполнена будет только первая, вторую сервер откинет. Из-за этого нюанса происходит много интересных вещей, поэтому всегда стоит помнить — необходимо стопроцентное выполнение конкретной задачи? — добавляй к параметрам уникальное значение.

    Сервер является процессом-демоном. Имеет достаточно много конфигурационных параметров, на ряду со стандартными для таких приложений настройками user-port-interface, имеется также несколько специфичных опций. Количество попыток выполнения задачи настраивается параметром -j, --job-retries=. Для использования нескольких потоков существует параметр -t, --threads=. Сервер имеет возможность сохранять очередь задач в какое-либо хранилище, чтобы при рестарте была возможность восстановить весь процесс без потери данных. Хранилищем может выступать MySQL/drizzle, memcached, PostgreSQL или sqllite. Более чем интересной является опция использования сторонних протоколов в процессе коммуникации клиент -> сервер задач. Единственным таким, имплементированным на данный момент, протоколом является HTTP. При помощи этой опции, можно настроить gearman сервер на приём задач по определённому порту через HTTP запрос (requested uri транслируется в task name, http body в workload, http headers соответственно в task type), то есть реализация клиента сводится к реализации простого HTTP клиента на вызывающей стороне. Никаких ограничений на тип/размер задачи это не накладывает. Подробнее об использовании HTTP в gearman можно почитать здесь. Используя HTTP протокол и Gearman построение эффективно сбалансированных REST сервисов может стать как никогда простой задачей. Cоздавать задачи для gearman можно практически из любого языка программирования, так как обёртки на вызовы функций API написаны для большинства сред.

    Исполняющая часть cоответственно находится в так называемом исполнителе. Здесь выбор средств реализации также очень обширен, начиная от стандартных php, python, java и заканчивая пользовательскими функциями в mysql. Единственное условие — наличие поддержки gearman библиотеки, что может потребовать дополнительной компиляции каких-либо модулей. Так называемый исполнитель (worker) является background процессом, после запуска регистрирует все задачи, которые он может выполнить и, находясь в памяти, ждёт поступления задач от сервера. Количество серверов, с которыми держит связь конкретный исполнитель — не ограничено.

    Поговорим о недостатках, их несколько, и они разной степени серьёзности. Так как исполнитель является долгоживущим процессом, то любое изменение его функциональности подразумевает под собой процесс перезапуска самого исполнителя, это же касается и добавления/удаления задач, которые может выполнить данный исполнитель. То есть, если нужно добавить новую функцию, или изменить уже существующую, нужно перезапустить все процессы исполнителей, которые связанны с выполнением данной задачей. Этот процесс, в случае, когда исполнители разбросаны по разным серверам, в разном количестве, не является тривиальным. Да и не все языки предназначены для написания эффективных процессов-демонов.

    Распределение задач сервером происходит только по одному единственному алгоритму — round robin. Да, существуют задачи с двумя уровнями приоритета — высокий и низкий. Но более точный контроль за выполнением задач недоступен. Более того, нельзя точно узнать, на каком из исполнителей будет выполнена задача, и также невозможно указать напрямую, которому узлу её послать, что сильно усложняет процесс отладки.

    Из описанных выше недостатков следует основной — отсутствие вменяемых средств управление реализованной системой. Всё приходится делать вручную, и всё время держать в голове структуру gearman приложения.

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

    Теперь немножко линков на источники информации и других интересностей о Gearman:
Tags:
Hubs:
Total votes 56: ↑52 and ↓4 +48
Views 36K
Comments 40
Comments Comments 40