python gevent在函数中是不可修补的

时间:2018-05-02 22:45:03

标签: python gunicorn gevent

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

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

我想使用gevent worker以便能够接收更多请求,因为并非每个端点都需要花费很长时间才能执行。但是,库中的函数不使用任何可修补的gevent函数,这意味着它不会合作安排到另一个绿色线程。

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

是否可以使用multiprocessing.Process与gevent?然后让join方法放弃对另一个绿色线程的控制,只在进程结束时返回?

1 个答案:

答案 0 :(得分:1)

是的,在gevent内使用(实际)线程或进程来完成合理的代码需要异步但不能由gevent进行修改。

当然,获得右键优先权可能很棘手,因为你可能有monkeypatched threading,其次,因为你希望你的协作线程能够阻塞池或池结果而不会阻塞整个主线。

但这正是gevent.threadpool的用途。

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

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

无论哪种方式,mapsubmitapply_async等方法的工作方式与您预期的方式非常相似。 FutureAsyncResult对象可以很好地与greenlets一起使用;你可以gevent.wait个东西,或附加回调(它将作为greenlets运行)等等。大多数时候它只是像魔术一样工作,其余的时间它不太难以弄明白。

使用进程代替线程是可行的,但不是很好。 AFAIK,对于multiprocessing.Processmultiprocessing.Pool完整的任何内容都没有包装,尝试使用普通multiprocessing只是挂起。您可以手动fork,如果您不在Windows上,但这是关于所有内置的。如果您真的需要多处理,您可能需要做一些多层次的事情,你的greenlets不与一个进程交谈,而是与一个创建管道,分支,高手,然后代理gevent世界和子进程之间的代理交谈。

如果电话花了很长时间,因为他们正在等待来自后端服务的I / O,或等待子进程,或者正在进行GIL释放numpy工作,我就不会费心去做做multiprocessing。但是如果他们花了很长时间因为他们正在燃烧CPU ......那么你需要让多处理工作,或者更低级别,然后剥离subprocess.Popen([sys.executable, 'workerscript.py'])