2017-02-13 72 views
0

假设我们有这是一个事件驱动单线程服务器上承载的WSGI应用:Eventlet在请求WSGI服务器和耗时的操作

from eventlet import wsgi 
import eventlet 

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

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

在应用程序的功能,一些I/O操作,因为必须执行读取文件或数据库访问。

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

问:什么是可能的解决方案来解决这个问题?我怎样才能让Eventlet wsgi服务器执行耗时的操作而不被阻塞?

回答

0

TL; DR:使用mysqldb/psycopg或eventlet.import_patched() pure 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文档。

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

相关问题