2017-02-13 3 views
0

Давайте предположим, что у нас есть приложение WSGI, которое размещено на событийного однопоточных сервер:Eventlet WSGI сервера и трудоемкие операции в запросах

from eventlet import wsgi 
import eventlet 

def app(env, start_response): 
    # IO opeartions here 
    ... 

wsgi.server(eventlet.listen(('', 8090)), app) 

В функции приложения, операции некоторые методы ввода/вывода так как файлы чтения или доступ к БД должны выполняться.

Теперь, когда мы выполняем операции ввода-вывода в приложении, сервер эффективно блокируется и не может обслуживать других клиентов.

Вопрос: Каковы возможные решения этой проблемы? Как я могу получить сервер WSOPs Eventlet, выполняющий отнимающие много времени операции, не блокируя его?

ответ

0

TL; DR: использовать mysqldb/psycopg или eventlet.import_patched() драйверы с чистым питоном python; tpool.execute() для файлов и всего остального.

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

Так что все, что ждет файлового дескриптора, является кандидатом на зелёный (не блокирующий). Самое главное, это влияет на все сетевые IO. Если ваша функция блокировки написана на чистом Python, просто используйте import_patched(module_name), чтобы изменить ее socket и другие ссылки на зеленую версию Eventlet. mysqldb и psycopg2 являются специальными случаями модулей расширения C, которые были объединены в благодарность за явную поддержку со стороны их авторов. Все остальное блокирует код не Python - ваш вариант - это потоки ОС.

К сожалению, ожидание на реальных дисковых файлах полна причуд, поэтому я рекомендую использовать потоки ОС, и у нас есть встроенный пул потоков для поддержки этого. Преобразуйте blocking_fun(filepath, something_else) в eventlet.tpool.execute(blocking_fun, filepath, something_else), и он не блокирует все. Подробную информацию см. В документации по tpool.

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

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