2013-04-12 49 views
11

我最近一直在使用烧瓶在python中进行宠物项目。这是一个简单的pastebin,带有pygments的服务器端语法突出显示支持。因为这是一个代价高昂的任务,我将语法突出显示委托给一个芹菜任务队列,并在请求处理程序中等待它完成。不用说,这只不过是减轻了另一名工作人员的CPU使用量,因为等待结果仍然会锁定与Web服务器的连接。 尽管我的直觉告诉我要避免像瘟疫一样的过早优化,但我仍然无法帮助自己寻找异步。Python异步和CPU绑定任务?

异步

如果最近一直下面的Python Web开发,你一定已经看到,异步无处不在。 async做的是带回合作多任务,这意味着每个“线程”决定何时何地屈服于另一个线程。这种非抢先式进程比OS线程更有效,但仍然有缺点。目前,似乎有两个主要途径:

  • 事件/回调风格的多任务
  • 协同程序

第一个通过一个事件循环执行的松耦合组件提供并发。虽然这对于竞争条件来说更安全并且提供了更多的一致性,但它比直接的多任务更直观,更难以编码。

另一种是比较传统的解决方案,更接近线程化编程风格,程序员只需手动切换上下文。虽然更容易出现竞态条件和死锁,但它提供了一种简单的插入式解决方案。

目前大多数异步工作都是在所谓的IO-bound上完成的任务,阻塞等待输入或输出的任务。这通常是通过使用基于轮询和基于超时的功能来完成的,如果它们返回负值,则可以切换上下文。

尽管名字,这可应用于CPU绑定任务也可以委托给其他员工(线程,进程等),然后无阻挡地等待屈服。理想情况下,这些任务将以异步友好的方式编写,但实际上这意味着将代码分成足够小的块以防止块,最好在每行代码之后不散射上下文切换。这对现有的同步库尤其不便。


由于方便,我定居在使用异步工作GEVENT,并想知道如何与在异步环境CPU密集型任务进行处理(利用期货,芹菜等?)。

如何在传统Web框架(如瓶子)中使用异步执行模型(本例中为gevent)? python中的这些问题(期货,任务队列)中的一些普遍认可的解决方案是什么?

编辑:更具体的 - 如何使用gevent与烧瓶以及如何处理在这种情况下的CPU绑定任务?

EDIT2:考虑到Python的GIL是如何阻止线程代码的优化执行的,所以这只留下多处理选项,至少在我的情况下。这意味着要么使用并发期货要么处理一些其他外部服务(可以为某些语言不可知的情况打开大门)。在这种情况下,什么会是一些流行或经常使用的gevent解决方案(,即芹菜)? - 最佳实践

+0

您几乎可以在每个库中采用此模式:http://bottlepy.org/docs/dev/async.html#event-callbacks。我建议'常青树',因为它允许通过集成'concurrent.futures'的修改版本来将合作任务(greenlet)与长时间运行的任务相结合。 – schlamar

回答

6

应该是线程安全的做一些像下面这样单独的CPU密集型任务到异步线程:

from threading import Thread 

def send_async_email(msg): 
    mail.send(msg) 

def send_email(subject, sender, recipients, text_body, html_body): 
    msg = Message(subject, sender = sender, recipients = recipients) 
    msg.body = text_body 
    msg.html = html_body 
    thr = Thread(target = send_async_email, args = [msg]) 
    thr.start() 

如果你需要更复杂一些的话,或许瓶,芹菜或多重使用“池库“可能对你有用。

我不太熟悉gevent,尽管我无法想象您可能需要什么更复杂或为什么。

我的意思是,如果您尝试提高主要世界网站的效率,那么我建议您构建C++应用程序来完成CPU密集型工作,然后使用Flask-celery或Pool来运行该进程。 (这是YouTube在混合C++时所做的工作& Python)

+0

任何来源的YouTube如何做它(博客或东西)? – nikitautiu

+0

我最终使用了芹菜,但正如我所说,等待结果最终会阻止网络服务器。解决方案是将服务器与gevent或gent worker的gunicorn服务器一起服务于WSGI应用程序。对于异步结果,我只是轮询'ready()',如果没有完成,我会用一个规范的'gevent.sleep()'产生。 – nikitautiu

+0

恐怕我没有链接,但谷歌博客可能是一个寻找它的地方。 – Dexter

1

如何简单地使用ThreadPool和Queue?然后你可以用一种独立的线程以同步的方式处理你的东西,你根本不用担心阻塞。那么,Python首先不适合CPU绑定的任务,所以你也应该考虑产生子流程。

+0

这是一个有效的解决方案,还有一些我可以考虑的问题。关键是,我想知道如何将gevent整合到烧瓶中,以及使用gevent的人如何处理边界不可能使同步任务变为“绿色”的情况。 – nikitautiu