Есть ли способ увидеть, какие библиотеки исправляются обезьянами при запуске celery с eventlet pool в приложении Django?
В настоящее время я запускаю проект Django, который разгружает работу на фоновые рабочие станции celery. Для задач, привязанных к процессору, пул вилок работает отлично и выполняется следующим образом:
celery -A myApp worker -l INFO -E -n worker --concurrency=<CPU-core-count>
Однако, с растущим набором длительно выполняющихся задач, в основном скрапирующих API из фоновых рабочих, я хочу создать отдельную очередь, чтобы использовать eventlet (или gevent pool) для лучшего масштабирования этих рабочих нагрузок.
Я запускаю eventlet таким образом, что он запускает worker и кажется нормальным, когда я тестирую его.
celery -A myApp worker -l INFO -E -n worker --concurrency=100 -p eventlet
Я протестировал две различные версии установки для eventlet. Сначала с этими версиями:
- Celery 5.1.0
- Eventlet 0.33
При выполнении этой установки я получаю ту же ошибку, что и здесь, когда делаю опросы API + запросы к базе данных в моих рабочих: Объекты DatabaseWrapper, созданные в потоке, могут быть использованы только в этом же потоке
В других предложениях предлагалось просто обновить eventlet и Celery до последней версии, и после того, как я это сделал, рабочие, кажется, работают хорошо с этой установкой:
- Celery 5.2.7
- Eventlet 0.33
Напоследок, я попробовал запустить gevent следующим образом для сравнения:
celery -A myApp worker -l INFO -E -n worker --concurrency=100 -p gevent
как с celery 5.2.7 и 5.1.0, так и с gevent 21.8.0. Похоже, потому что Django не очень хорошо работает с асинхронными ORM-запросами к базе данных, время от времени некоторые задачи завершаются с ошибкой SynchronousOnlyOperation.
Нет точного алгоритма, по которому я могу воспроизвести эту проблему, и она возникает случайным образом, по-видимому, при постановке в очередь большего количества задач, чем установлено в настройках параллелизма celery, и, очевидно, при выполнении запросов к Django ORM. В целом, как я вижу, другие предлагают обернуть ORM-запросы Django в async_to_sync, поддерживаемый в Django < 4.1 или использовать недавнее обновление Django 4.1, где они сделали асинхронную поддержку для большинства ORM-запросов. В настоящее время мы не готовы к обновлению до 4.1, и это значительно усложнит наши задачи, если мы будем использовать обёртки async_to_sync.
В целом, я не против использования eventlet, который до сих пор работал в тестировании, учитывая, что я использую последние обновления для celery и eventlet. Но в то же время я немного не хочу использовать это в производстве, пока не пойму:
- Как eventlet работает с Django ORM (поскольку ORM, очевидно, не очень хорош в асинхронных контекстах)
- Если eventlet имеет такие же проблемы с ORM Django, как и gevent при сильном параллелизме, рискуя вызвать исключения SynchronousOnlyOperation. (Я не нашел никаких сообщений об этом для eventlet на Stackoverflow или в других местах, только для пула gevent) .
- Почему предыдущая проблема в eventlet, о которой я говорил выше, исчезла в последних версиях и как я могу знать, что она не может возникнуть при определенных обстоятельствах, которые я не смог найти.
- И, наконец, есть ли способ проверить, исправляются ли коннекторы баз данных или другие критически важные библиотеки Django, используя eventlet. Большая часть поддержки патчей кажется магической, по крайней мере, при использовании eventlet в Celery, так что есть ли хороший способ увидеть, что происходит под капотом?
Краткое описание тестирования:
Настройка celery для событий + создание ORM-запросов и API опросов Django:
celery -A myApp worker -l INFO -E -n worker --concurrency=100 -p gevent
Библиотеки
- Celery 5.1.0 / Celery 5.2.7
- gevent 21.8.0
Время от времени бросает SynchronousOnlyOperation из-за выполнения асинхронных запросов.
Настройка celery eventlet + выполнение ORM запросов и опрос API:
celery -A myApp worker -l INFO -E -n worker --concurrency=100 -p eventlet
Библиотеки:
- Celery 5.1.0
- Eventlet 0.33
Queries fails with: Объекты DatabaseWrapper, созданные в потоке, могут быть использованы только в этом же потоке
celery -A myApp worker -l INFO -E -n worker --concurrency=100 -p eventlet
Библиотеки:
- Celery 5.2.7
- Eventlet 0.33
Похоже, что работает, никаких проблем при тестировании пока не обнаружено, но нет возможности знать, что это работает при всех обстоятельствах, учитывая предыдущие тесты с gevent и eventlet