суббота, 29 мая 2010 г.

Сетевая очередь задач (Task Queue)

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

Как вы уже поняли в качестве базового компонента используется сервер приложений из предыдущего поста. Обмен между потоками осуществляется по HTTP протоколу. Интерфейс доступа к очереди осуществляется с помощью 4 методов: qsize, get, set, task_done. Прежде чем продолжить с описанием каждого из методов следует упомянуть об общем для этих методов правиле - формате URL запроса:
/<worker_name>/<method>/
worker_name - текстовое имя процесса, которому адресуется задача
method - имя метода: qsize, get, set, task_done

Оба этих поля являются обязательными. Имя процесса необходимо для разграничения задач между процессами. Аналогия с рабочими, один маляр, другой плотник, третий слесарь. Каждый умеет делать что-то свое, следовательно у каждого свои задачи.

Теперь остановимся на каждом из методов подробнее:

qsize
возвращает размер очереди.
- Формат запроса (GET): /<worker_name>/qsize/
- Возвращает результат: { "worker": <worker_name>, "qsize": <qsize> }

put
помещает задачу в очередь
- Формат запроса (POST): /<worker_name>/put/
- Возвращает результат: { "worker": <worker_name>, "task_id": <task_id> }

Все пары значений переданных в запросе POST считаются как исходные данные для задачи, за исключением пары worker=<worker_name>. Эта пара зарезервирована для внутренних нужд, поэтому во избежании конфликтов и ошибок не стоит ее использоваться при передаче в запросе POST

get
извлекает задачу из очереди
- Формат запроса (GET): /<worker_name>/get/
- Возвращает результат: { "worker": <worker_name>, "task_id": <task_id>, "task": <task> }

task_done
маркирует, что задача выполнена
- Формат запроса (GET): /<worker_name>/done/<task_id>
- Возвращает результат: { "worker": <worker_name>, "task_id": <task_id>, "task": <task> }

Методы put, get, task_done в случае успешности операции возвращают уникальный идентификатор задачи, иначе поле task_id содержит пустую строку.

Открытый интерфейс и простота решения с одной стороны являются достоинствами, но с другой являются и недостатками о которых следует знать.
- Очередь задач, как и сервер приложений не удовлетворяют требованиям безопасности. В данной версии любой может оказать влияние на работу очереди из вне, для этого достаточного простого броузера, через адресную строку которого можно выполнять запросы к очереди задач.
- Число задач в очереди не лимитируется. Это может привести к перерасходу ресурсов если число процессов добавляющих задачи будет больше процессов их решающих.
- Не контролируется время выполнения задачи. Возможна ситуация, когда все задачи будут распределены между процессами, но не выполнены. Они будут числиться в списке активных задач. В будущих версиях будет добавлена возможность определения длительности выполнения задачи, по истечении которой, задачи из списка активных задач будет возвращены в список задач на выполнение.

Исходный код очереди задач

0 комментариев:

Отправить комментарий