недавно мы перешли на Gunicorn с помощью работника gevent.
На нашем веб-сайте у нас есть несколько задач, выполнение которых требует времени. Дольше 30 секунд.
Преамбула
Мы уже сделали все, что связано с сельдереем, но эти задачи выполняются так редко, что просто невозможно постоянно поддерживать сельдерей и redis в рабочем состоянии. Мы просто этого не хотим. Мы также не хотим запускать сельдерей и редис по запросу. Мы хотим от этого избавиться. (Прошу прощения, но я не хочу, чтобы ответы были такими: «Почему бы тебе не использовать сельдерей, это здорово!»)
Задачи, которые мы хотим запускать асинхронно
Я говорю о задачах, которые выполняют 3000 SQL-запросов (вставок), которые должны выполняться один за другим. Это делается не слишком часто. Мы также ограничились запуском только двух из этих задач одновременно. Это займет примерно 2–3 минуты.
Подход
Теперь то, что мы делаем сейчас, - это использование gevent worker и gevent.spawn
задачи и возвращение ответа.
Эта проблема
Я обнаружил, что порожденные потоки на самом деле блокируются. Как только ответ возвращается, задача запускается, и никакие другие запросы не обрабатываются до тех пор, пока задача не прекратит выполнение. Задание будет убито через 30 секунд, пулемет timeout
. Чтобы предотвратить это, я использую time.sleep()
после каждого второго SQL-запроса, чтобы сервер мог ответить на запросы, но я не думаю, что это главное.
Установка
Мы запускаем gunicorn, django и gevent. Описанное поведение происходит в моей среде разработки и при использовании одного работника gevent. В производстве мы также будем запускать только 1 рабочего (пока). Кроме того, запуск двух воркеров, похоже, не помогал в обслуживании большего количества запросов во время блокировки задачи.
TL; DR
- Мы считаем возможным использовать поток gevent для нашей двухминутной задачи (над сельдереем)
- Мы используем gunicorn с gevent и задаемся вопросом, почему поток, порожденный gevent.spawn, блокирует
- Блокировка предназначается или наши настройки неверны?
Спасибо!
time.sleep
, будут по-прежнему блокироваться внутри гринлета. Вы должны использоватьgevent.sleep
, чтобы сделать неблокирующий сон. Ваши вызовы базы данных, вероятно, тоже блокируются, если вы не используете исправление обезьяны gevent. - person dano   schedule 02.07.2014time.sleep
допускает изменение потока, поэтому это не блокирует. Может быть, заплатка обезьяны исправила это. Но я ожидал передать задачу работнику, который затем позаботится о ней. Таким образом, он может блокировать все, что хочет, пока работает параллельно. Но я думаю, что гринлеты нельзя запускать параллельно? - person enpenax   schedule 02.07.2014gevent.sleep
, другой гринлет может работать. Но если один гринлет обрабатывает числа или анализирует XML (или любую другую операцию на базе процессора), никакие другие гринлеты работать не будут. Гринлет также будет блокировать другие гринлеты, если он выполняет операцию ввода-вывода, которая не является асинхронной, то есть это не обезьяна, исправленная gevent или иным образом подключенная к циклу событий gevent. - person dano   schedule 02.07.2014