2013-02-13 10 views
5

Я пытаюсь выполнять длительные запросы с использованием gunicorn и его асинхронных рабочих, но я не могу найти примеров, которые я могу получить для работы. Я использовал пример here но переделан, чтобы добавить поддельную задержку (сон в течение 5 секунд), прежде чем вернуться в ответ:gunicorn не обрабатывает одновременные запросы одновременно

def app(environ, start_response): 
    data = "Hello, World!\n" 
    start_response("200 OK", [ 
     ("Content-Type", "text/plain"), 
     ("Content-Length", str(len(data))) 
    ]) 
    time.sleep(5) 
    return iter([data]) 

Тогда я бег gunicorn так:

gunicorn -w 4 myapp:app -k gevent

Когда я открываю два браузера вкладки и введите в http://127.0.0.1:8000/ в обоих из них и отправьте запросы почти в одно и то же время, запросы, как представляется, будут обработаны последовательно - один возвращается через 5 секунд, а другой возвращается после далее 5 секунд.

В. Я полагаю, что сон не дружелюбен? Но есть 4 работника, и даже если тип работника «синхронизируется», два работника должны одновременно обрабатывать два запроса?

+0

Вопрос: Вы нашли решение? –

+0

Прости, я этого не делал. – swoop81

ответ

5

Я просто столкнулся с тем же, открыл здесь вопрос: Requests not being distributed across gunicorn workers. В результате получается, что браузер выполняет сериализацию доступа к той же странице. Я предполагаю, что, возможно, это что-то делать с кэшированием, т. Е. Браузер считает, что, вероятно, страница кэшируема, подождите, пока она загрузит обнаружит, что это не так, что она делает другой запрос и так далее.

+0

Так раздражает и так просто ... :( – jwg

+0

Спасибо @CrazyCasta. Я проверил ваш ответ, установив другой браузер и отправляя запросы от двух отдельных браузеров (хром и firefox) одновременно, и запросы выполняются параллельно. – swoop81

0

Дайте gevent.sleep снимок вместо time.sleep.

Странно, что это происходит с -w 4, но -k gevent - это тип рабочего типа асинхронного типа, поэтому возможно, что пушечный огонь подает оба запроса одному и тому же клиенту. Предполагая, что это происходит, time.sleep заблокирует ваш процесс, если вы не используете gevent.monkey.patch_all().

1

При использовании пушки с неблокирующим рабочим типом, например gevent, он будет использовать ТОЛЬКО ОДИН процесс, связанный с запросами, поэтому неудивительно, что ваша 5-секундная работа выполнялась последовательно.

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

UPDATE

Я был неправ.

При использовании пушки с неблокирующим рабочим типом с рабочими настройками в стрельбе каждый рабочий - это процесс, который запускает отдельную очередь.

Так что, если time.sleep запускался на разных процессах, он запускается одновременно, но когда он работает у одного и того же работника, он будет выполняться последовательно.

Проблема заключается в том, что балансировщик стрельбы из пушки может не распространять два запроса на два рабочих процесса. Вы можете проверить текущий процесс на os.getpid().

+0

Gunicorn не использует только один процесс для обработки запросов, он использует номер, указанный вами как флаг '-w'. –

+0

@ ron.rothman Это правда! Мое ​​объяснение неверно, спасибо за упоминание. – tdihp

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