Eventlet wsgi服务器和请求中耗时的操作

时间:2017-02-13 13:07:04

标签: python wsgi eventlet

假设我们有一个WSGI应用程序,它托管在一个事件驱动的单线程服务器上:

from eventlet import wsgi
import eventlet

def app(env, start_response):
    # IO opeartions here
    ...

wsgi.server(eventlet.listen(('', 8090)), app)

在app功能中,必须执行一些I / O操作,如读取文件或DB访问。

现在,当我们在app中执行IO操作时,服务器被有效阻止,无法为其他客户端提供服务。

问:这个问题有哪些可行的解决方案?如何在不被阻止的情况下让Eventlet wsgi服务器执行耗时的操作?

1 个答案:

答案 0 :(得分:0)

TL; DR:使用mysqldb / psycopg或eventlet.import_patched()纯python DB驱动程序; tpool.execute()用于存放文件和其他所有内容。

尝试将您的思维过程修复为分离操作,这些操作可以转换为与Eventlet的合作以及那些不可能的合作。这里的合作意味着分成“执行代码” - “等待结果”部分,并在结果准备好时提供通知机制。 Eventlet的主要通知机制是文件描述符。

所以等待文件描述符的一切都是绿色(不阻塞)的候选者。最重要的是,它会影响所有网络IO。如果您的阻塞函数是用纯Python编写的,只需使用import_patched(module_name)修改其socket和其他对Eventlet绿色版本的引用。 mysqldbpsycopg2是C扩展模块的特殊情况,合作感谢其作者的明确支持。非Python代码中阻塞的所有其他内容 - 您的选项是操作系统线程。

不幸的是,等待实际的磁盘文件充满了怪癖,所以我建议使用操作系统线程,我们有内置的线程池来支持它。将blocking_fun(filepath, something_else)转换为eventlet.tpool.execute(blocking_fun, filepath, something_else)并且它不会阻止所有内容。查看tpool文档了解详细信息。

如果可以,请将整个应用程序重新设计为阻塞和非阻塞进程,并让它们通过套接字进行通信。从代码重写的角度来看这很难,但对于运行时调试非常简单;强大且防故障的设计。