Celery + Eventlet + 非阻塞请求

11

我正在使用Python的requests库在celery的workers中进行大量(约10个/秒)的API调用(包括GET,POST,PUT,DELETE)。每个请求需要大约5-10秒完成。

我尝试在具有1000并发的eventlet池中运行celery工作进程。

由于requests是阻塞进程,因此每个并发连接都在等待一个请求。

如何使requests异步化?

2个回答

19

使用 eventlet monkey patching,使任何纯 Python 库变为非阻塞。

  • 补丁单个库

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

可以将 erequestsgrequests 软件包简化为以下两行。

  • 对一切进行打补丁。

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

    更新:关于猴子补丁requests库的已知问题。如果你遇到以下情况:

    ImportError: cannot import name utils
    

    然后修改导入行为

    requests = eventlet.import_patched('requests.__init__')
    

    1
    完美! 唯一的问题是我无法执行 requests = eventlet.import_patched('requests') 它会报错无法导入utils (from . import utils) 所以我已经根据https://github.com/eventlet/eventlet/issues/7将其更改为 requests = eventlet.import_patched('requests.__init__')再次感谢 - Maddy
    @Maddy,除了修补请求库之外,还需要做些什么才能使请求异步化?在请求后收集响应的方式是否有任何变化?在修补后,我们是否仍然可以执行resp = requests.get("http://google.com")? - amrx
    @amrx 当时它是有效的,但我相信他们现在一定更新了补丁。 - Maddy
    除了修补程序之外,一切都按预期运行。 - temoto
    @temoto,你需要打补丁吗?文档并不确定,即使是gevent和eventlet的官方示例也没有打补丁。https://github.com/celery/celery/blob/master/examples/gevent/tasks.py - amrx
    1
    @amrx 您必须执行 eventlet.monkey_patch() 或使用 eventlet.import_patched('module_name') 来处理每个具有网络代码的模块。如果您指定了 eventlet 工作类型,Celery 会隐式执行第一种选项。https://github.com/celery/celery/blob/b5b64945daaba87a7d975b1b4fca08b0948b91bb/celery/__init__.py#L99 - temoto

    3

    请编辑答案,加入此链接,以便我可以接受它。 - Maddy

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接