Celery + Eventlet + неблокирующие запросы

Я использую Python requests в celery workers для выполнения большого количества (~ 10/сек) вызовов API (включая GET, POST, PUT, DELETE). Каждый запрос занимает около 5-10 секунд.

Я попытался запустить сельдерейных рабочих в пуле eventlet с параллелизмом 1000.

Поскольку requests блокируют процесс, каждое параллельное соединение ожидает одного запроса.

Как сделать requests асинхронным?


person Maddy    schedule 04.02.2015    source источник


Ответы (2)


Используйте eventlet исправление обезьяны, чтобы сделать любую чистую библиотеку Python неблокирующей.

  • исправление одной библиотеки

    # import requests  # instead do this:
    import eventlet
    requests = eventlet.import_patched('requests')
    

    пакеты erequests и запросы можно сократить до этих двух строк.

  • исправить все

    import eventlet
    eventlet.monkey_patch()  # must execute as early as possible
    ...
    # everything is non-blocking now:
    import requests, amqp, memcache, paramiko, redis
    

Обновление: существует известная проблема с библиотекой запросов на исправление обезьян. Если вы получаете:

ImportError: cannot import name utils

, затем измените строку импорта на

requests = eventlet.import_patched('requests.__init__')
person temoto    schedule 04.02.2015
comment
Идеальный ! Единственная проблема заключалась в том, что я не смог сделать requests = eventlet.import_patched('requests'), он не мог импортировать утилиты (from . import utils). Поэтому я изменил его на requests = eventlet.import_patched('requests.__init__') в соответствии с github.com/eventlet/eventlet/issues/7 еще раз спасибо - person Maddy; 05.02.2015
comment
@Maddy, помимо исправления библиотеки запросов, требовалось ли что-то еще для асинхронного выполнения запросов, а также были ли какие-либо изменения в способе сбора ответа после запроса? Можем ли мы после внесения исправлений выполнить resp = request.get(google.com)? - person amrx; 30.03.2017
comment
@amrx В то время это работало, но я уверен, что сейчас они обновили исправление. - person Maddy; 31.03.2017
comment
@amrx, кроме исправления, все работает как положено. - person temoto; 31.03.2017
comment
@temoto, патчить надо? В документации нет уверенности в этом, и даже официальные примеры gevent и eventlet не исправляются.github.com/celery/celery/blob/master/examples/gevent/tasks.py - person amrx; 31.03.2017
comment
@amrx Вы должны либо выполнить eventlet.monkey_patch(), либо использовать eventlet.import_patched('module_name') для каждого модуля с сетевым кодом. Celery делает первый вариант неявно, если вы укажете тип работника eventlet. github.com/celery/celery/blob/ - person temoto; 01.04.2017

из документов:

существует множество проектов, в которых запросы сочетаются с одной из сред асинхронности Python. Два превосходных примера: grequests и запросы-фьючерсы.

конкретно для eventlet вы можете использовать erequests.

person WeaselFox    schedule 04.02.2015
comment
Пожалуйста, отредактируйте ответ, чтобы включить эту ссылку, чтобы я мог принять ее. - person Maddy; 04.02.2015