2009-11-04 3 views
3

У меня есть функция python (ну, теперь это PHP, но мы переписываем), которая принимает некоторые параметры (A и B) и вычисляет некоторые результаты (находит лучший путь от A до B в графе, граф доступен только для чтения) , в типичном сценарии один вызов занимает от 0,1 до 0,9 с. Эта функция доступна пользователям как простой веб-сервис REST (GET bestpath.php? From = A & to = B). Текущая реализация довольно глупа - это простой скрипт php + apache + mod_php + APC, каждый запрос должен загружать все данные (более 12 МБ в массивах php), создавать все структуры, вычислять путь и выходить. Я хочу изменить его.Как обрабатывать длительные запросы в python-работниках?

Я хочу установить с N независимых работников (X на сервер с серверами Y), каждый рабочий является приложением python, работающим в цикле (получение запроса -> обработка -> отправка ответа -> получение req ...) каждый рабочий может обрабатывать один запрос за раз. Мне нужно что-то, что будет действовать как интерфейс: получать запросы от пользователей, управлять очередью запросов (с настраиваемым таймаутом) и кормить моих работников по одному запросу за раз.

Как подойти к этому? можете ли вы предложить некоторые настройки? nginx + fcgi или wsgi или что-то еще? HAproxy? как вы можете видеть, что я новичок в python, обратный прокси и т. д. Мне просто нужна начальная точка архитектуры (и потока данных)

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

ответ

1

Типичным способом обработки такого рода размещения с использованием потоков в Python является использование стандартного библиотечного модуля Queue. Пример использования модуля Queue для управления рабочими можно найти здесь: Queue Example

2

Похоже, что вам нужны «рабочие», чтобы быть отдельными процессами (по крайней мере некоторые из них, и, следовательно, могли бы также сделать их все отдельными процессами, а чем пучки нитей, разделенных на несколько процессов). Модуль multiprocessing в Python 2.6 и более поздняя стандартная библиотека предлагают хорошие возможности для создания пула процессов и общения с ними через очереди «FIFO»; если по какой-то причине вы застряли с Python 2.5 или даже раньше, есть версии многопроцессорности в репозитории PyPi, которые вы можете скачивать и использовать с более старыми версиями Python.

«frontend» может и должен быть легко выполнен для работы с WSGI (с Apache или Nginx), и он может обрабатывать все сообщения с рабочими процессами с помощью multiprocessing без необходимости использования HTTP, проксирования и т. д. для этой части системы; только внешний интерфейс будет веб-приложением как таковым, рабочие просто получают, обрабатывают и реагируют на единицы работы, как того требует внешний интерфейс. Для меня это кажется самой простой и простой архитектурой.

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

+0

многопроцессорность выглядит нормально, но, честно говоря, мне не нужны все функции (связь, синхронизация и т. Д.), Мои работники независимы и с этой настройкой мне нужен интерфейс на каждом сервере, не так ли? я думал о внедрении базового анализа http (или что-то еще, я не знаю, какой другой протокол может использоваться между рабочим и revproxy) в рабочем месте, и пусть некоторый обратный прокси запрашивает обработку через пул серверов (рабочие порождаются на в начале), но я не знаю, имеет ли этот подход смысл и с чего начать (какой revproxy, как реализовать рабочий <-> revproxy и т. д.) – winter

+0

Вам не нужна синхронизация, кроме как для связи, но вам нужна коммуникация (от задач от внешнего интерфейса до рабочих, результатов от рабочих до интерфейса - нет, вам определенно НЕ нужен интерфейс на сервер, почему вы думаете, что ?!) и Queue, предоставленная многопроцессорной обработкой, отлично подходит для этого , освобождая вас от беспокойства по поводу протоколов, проксирования и еще чего-то - я думаю, что направление, к которому вы стремитесь, может запутать вас в настоящий беспорядок работы, в то время как многопроцессорность намного проще в использовании! –

+0

ОК, но с многопроцессорной обработкой мне нужно написать 2 приложения: app1 - один интерфейс управления процессом, app2 - много рабочих процессов, не так ли? то: может ли app1 управлять app2 на разных машинах?является постоянным? я имею в виду - его код и данные остаются между запросами с веб-сервера? если нет - очередь потеряна, если да - она ​​должна быть асинхронной, чтобы обрабатывать одновременные запросы. поэтому app1 в основном имитирует async webserver - его единственная цель - управлять очередью запросов. я бы хотел избежать дублирования функций, которые уже там усложняют. – winter

0

Я думаю, что вы можете настроить modwsgi/Apache поэтому он будет иметь несколько «горячих» интерпретаторов Python в отдельных процессах, готовых идти в любое время, а также использовать их для новых доступов (и породить новый, если они все занятый). В этом случае вы можете загрузить все предварительно обработанные данные в виде глобальных глобалов, и они будут загружаться только один раз за процесс и будут повторно использоваться для каждого нового доступа. На самом деле я не уверен, что это не стандартная конфигурация для modwsgi/Apache.

Основная проблема заключается в том, что вы можете в конечном итоге потреблять много «основной» памяти (но это тоже не проблема). Я думаю, вы также можете настроить modwsgi для одного процесса/несколько потоков , но в этом случае вы можете использовать только один процессор, потому что из Python Global Interpreter Lock (печально известный GIL), я думаю.

Не бойтесь спросить в списке рассылки modwsgi - они очень отзывчивый и дружелюбный.

+0

Новые процессы появляются только в Apache/mod_wsgi, если используется встроенный режим, и что это происходит, это функция Apache, а не mod_wsgi. Из памяти, описанной в разделе «http://code.google.com/p/modwsgi/wiki/ProcessesAndThreading». –

+0

О, и также следует упомянуть, что использование встроенного режима для получения этой функции имеет свои проблемы, когда задействовано много данных/памяти. См. «Http://blog.dscpl.com.au/2009/03/load-spikes-and-excessive-memory-usage.html». –

0

Вы можете использовать балансировщик нагрузки nginx для прокси-сервера PythonPaste paster (который обслуживает WSGI, например Pylons), который в любом случае запускает каждый запрос как отдельный поток.

1

Существует много модулей FastCGI с предварительно запрограммированным режимом и интерфейсом WSGI для питона вокруг, наиболее известным является flup. Мое личное предпочтение для такой задачи - superfcgi с nginx. Оба запускают несколько процессов и будут отправлять запросы к ним. 12Mb не так много, чтобы загружать их отдельно в каждом процессе, но если вы хотите делиться данными между рабочими, вам нужны потоки, а не процессы. Обратите внимание, что тяжелая математика в python с одним процессом и многими потоками не будет эффективно использовать несколько CPU/ядер из-за GIL. Вероятно, наилучшим подходом является использование нескольких процессов (столько, сколько у вас есть ядер), каждый из которых запускает несколько потоков (режим по умолчанию - superfcgi).

+0

спасибо за ссылки, я не знал о superfcgi. я знаю о GIL, и мои рабочие интенсивно «математики», поэтому я хочу, чтобы каждый из них был в своем собственном процессе. Мне не нужна связь между работниками. почему вы считаете, что настройка с процессами - это лучший подход? Я имею в виду, что точка потоков, когда вы хотите вычислить так быстро, как вы можете? – winter

+0

также, какой слой (nginx? Superfcgi? My app?) Отвечает за очередность в этой настройке (worker = process, no threads)? Например: у меня есть 4 сотрудника, каждый из которых может обрабатывать один запрос за раз, теперь у меня есть 10 запросов от пользователей, 4 из них идут прямо в рабочих, но как насчет 6? они должны оставаться в очереди FIFO в течение X секунд. – winter

+0

Слушающий сокет похож на очередь. Параметр 'backlog' соответствует максимальному количеству запросов, ожидающих приема. Каждый рабочий (процесс или поток) в 'superfcgi' принимает только тогда, когда он готов обрабатывать запрос. Таким образом, ОС выполняет все очереди для вас. –

1

Самое простое решение в этом случае - использовать веб-сервер для выполнения всего тяжелого подъема. Почему вы должны обрабатывать потоки и/или процессы, когда веб-сервер сделает все, что для вас?

Стандартное расположение в развертывании Питона:

  1. Вебсервер начать ряд процессов, каждый из которых выполняет полный интерпретатор питона и при необходимости загружать все данные в памяти.
  2. запрос HTTP приходит и получает отправляется в какую-то процесс
  3. Процесс делает свой расчет и возвращает результат непосредственно на веб-сервер и пользователь
  4. Если вам необходимо изменить свой код или данные графика, перезагрузки веб-сервера и вернитесь к шагу 1.

Это архитектура, используемая Django и другие популярные веб-фреймворки.

+0

ОК, но я хочу, чтобы мой код приложения и данные оставались между запросами, я не хочу, чтобы интерпретатор загружался по каждому запросу. это то, как это работает? – winter

+0

и что происходит, когда нет свободного процесса (рабочего) для обработки запроса? есть ли какой-то король очереди fifo (с таймаутом)? (извините за мои вопросы о новинках, которые я пришел из мира php;) – winter

+0

Код приложения и данные хранятся в памяти до тех пор, пока процесс жизни, т.е. навсегда или пока вы не перезапустите его. Это зависит от конфигурации веб-сервера, Apache позволит вам установить максимальное количество запросов на процесс. В общем, веб-сервер будет генерировать новые процессы, когда это необходимо. Это можно настроить по длине. См. MinSpareServers и MaxSpareServers в документах Apache. – knutin

0

Другим вариантом является таблица очередей в базе данных.
Рабочие процессы выполняются в цикле или вне cron и опроса таблицы очередей для новых заданий.

 Смежные вопросы

  • Нет связанных вопросов^_^