在进行Gevent / Eventlet猴子修补之后 - 我可以假设每当数据库驱动程序(例如 redis-py , pymongo )通过标准库使用IO时(例如{{1它将是异步的吗?
所以使用eventlets猴子修补就足以使例如: redis-py 在eventlet应用程序中无阻塞?
据我所知,如果我关注连接使用(例如,为每个greenlet使用不同的连接)应该足够了。但我想确定。
如果您知道还需要什么,或者如何使用Gevent / Eventlet正确使用数据库驱动程序,请同时输入。
答案 0 :(得分:16)
如果满足以下所有条件,您可以假设它会被神奇地修补。
socket
或eventlet
/ gevent
monkeypatches的其他内容构建的。没有文件,没有本机(C)套接字对象等aggressive=True
传递给patch_all
(或patch_select
),或者您确定该库未使用select
或类似内容。patch_thread
可能可以工作,但可能没有。)如果您不确定,那么测试非常简单 - 可能比阅读代码并尝试解决它更容易。有一个greenlet只做这样的事情:
while True:
print("running")
gevent.sleep(0.1)
然后让另一个对数据库运行慢查询。如果它是monkeypatched,循环greenlet将保持打印“运行”10次/秒;如果没有,当查询阻止程序时,循环greenlet将无法运行。
那么,如果您的驱动程序阻止,您会怎么做?
最简单的解决方案是使用真正并发的线程池进行数据库查询。我们的想法是,您将每个查询(或批处理)作为线程池作业启动,并在完成该作业时对您的gevent
进行绿色阻止。 (对于非常简单的情况,你不需要很多并发查询,你可以为每个查询生成一个threading.Thread
,但通常你无法逃脱。)
如果驱动程序执行了大量的CPU工作(例如,您正在使用运行进程内缓存的内容,甚至是像sqlite这样的整个进程内DBMS),那么您希望此线程池实际上是在进程之上实现的,因为否则GIL可能会阻止您的greenlets
运行。否则(特别是如果您关心Windows),您可能想要使用OS线程。 (但是,这意味着您不能patch_threads()
;如果您需要这样做,请使用流程。)
如果你正在使用eventlet
,并且想要使用线程,那么就有一个名为tpool
的内置简单解决方案就足够了。如果您使用的是gevent
,或者您需要使用流程,则无法使用。不幸的是,在eventlet
和gevent
之间阻塞greenlet(不阻塞整个事件循环)在tpool
和ThreadPoolExecutor
之间有点不同,并且没有很好地记录,但ProcessPoolExecutor
来源应该给你这个主意。除此之外,其余部分仅使用concurrent.futures
(如果您需要在2.x或3.1中使用此内容,请参阅p futures
)来执行threading
或{{1}上的任务}。 (或者,如果您愿意,可以直接转到multiprocessing
或futures
,而不是使用multiprocessing
。)
你能解释为什么我应该在Windows上使用OS线程吗?
快速摘要是:如果您坚持使用线程,您几乎可以编写跨平台代码,但如果您使用流程,则可以有效地为两个不同的平台编写代码。
首先,阅读ProcessPoolExecutor
模块的Programming guidelines(“所有平台”部分和“Windows”部分)。幸运的是,DB包装器不应该遇到大部分问题。您只需要通过tpool
处理流程。而且,无论是在游标操作级别还是查询级别进行包装,所有参数和返回值都将是可以被pickle的简单类型。不过,这是你必须小心的事情,否则不会成为问题。
与此同时,Windows的进程内同步对象的开销非常低,但其进程间的开销却非常高。 (它也有非常快的线程创建和非常慢的进程创建,但如果你使用池,这并不重要。)那么,你如何处理它?我有很多乐趣创建操作系统线程来等待跨进程同步对象并发出greenlet的信号,但你对乐趣的定义可能会有所不同。
最后,ppool
可以简单地适用于Unix的{{1}},但是在Windows上需要更多的工作(并且您必须了解Windows才能完成这项工作)。
答案 1 :(得分:2)
abarnert的回答是正确而且非常全面的。我只想补充一点,在eventlet中没有“激进”的补丁,可能是gevent功能。此外,如果库使用select
这不是问题,因为eventlet也可以修补它。
事实上,在大多数情况下eventlet.monkey_patch()
就是你所需要的。当然,必须在创建任何套接字之前完成。
如果您仍有任何问题,请随时打开问题或写信给eventlet邮件列表或G +社区。所有相关链接均可在http://eventlet.net/
找到