【问题标题】:python gevent in function that is not patchable无法修补的函数中的python gevent
【发布时间】:2018-10-13 03:38:03
【问题描述】:

我在一个 REST 服务中工作,它基本上是一个库的包装器。我正在使用烧瓶和gunicorn。基本上,服务中的每个端点都映射到库中的不同函数。

碰巧一些对库的调用可能需要很长时间才能返回,这使得一旦服务开始接收一些请求,我的服务就会耗尽工作人员。现在我正在使用默认的 gunicorn workers(同步)。

我想使用 gevent worker 来接收更多请求,因为不是每个端点都需要这么长时间来执行。但是库中的函数不使用任何可修补的 gevent 函数,这意味着它不会协同调度到另一个绿色线程。

我的想法是使用线程池或进程池来异步处理对库的调用,然后 gunicorn 生成的每个绿色线程都会休眠,直到进程未完成。这个想法有意义吗?

是否可以将 multiprocessing.Process 与 gevent 一起使用?然后有join方法把控制权交给另一个绿色线程,等进程结束才返回?

【问题讨论】:

    标签: python gunicorn gevent


    【解决方案1】:

    是的,将gevent 中的(真实)线程或进程用于需要异步但不能由gevent 进行monkeypatched 的代码非常有意义。

    当然,正确处理可能很棘手——首先,因为您可能已经对 threading 进行了猴子补丁,其次,因为您希望协作线程能够阻塞池或池结果而不阻塞整个主线程线程。

    但这正是gevent.threadpool 的用途。

    如果您在非gevent 应用程序中使用concurrent.futures.ThreadPoolExecutor,请使用monkeypatch threading,然后使用gevent.threadpool.ThreadPoolExecutor

    如果您在非gevent 应用程序中使用multiprocessing.dummy.Pool,请使用monkeypatch threading,然后使用gevent.threadpool.ThreadPool

    无论哪种方式,mapsubmitapply_async 等方法都可以按照您的预期工作。 FutureAsyncResult 对象与greenlets 配合得很好;你可以gevent.wait 东西,或者附加回调(它将作为greenlets 运行)等等。大部分时间它就像魔术一样工作,而其余时间并不难弄清楚。


    使用进程而不是线程是可行的,但不是很好。 AFAIK,没有像multiprocessing.Processmultiprocessing.Pool 这样完整的包装,并且尝试使用普通的multiprocessing 只是挂起。如果你不在 Windows 上,你可以手动 fork,但这就是内置的所有内容。如果你真的需要多处理,你可能需要做一些多层的事情,你的 greenlet 不与进程对话,而是与在 gevent 世界和子进程之间创建管道、fork、exec 和代理的线程交谈。

    如果调用需要很长时间,因为它们正在等待来自后端服务的 I/O、等待子进程或执行 GIL 释放 numpy 工作,我不会费心尝试执行 multiprocessing .但是,如果他们因为消耗 CPU 而需要很长时间……那么,您要么需要让多处理工作正常工作,要么转到较低级别,然后分拆 subprocess.Popen([sys.executable, 'workerscript.py'])

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-06-14
      • 1970-01-01
      • 2017-04-29
      • 1970-01-01
      • 1970-01-01
      • 2012-05-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多