龙卷风真的是非阻塞的吗?

19

Tornado宣传自己是一个“相对简单的、非阻塞式Web服务器框架”,旨在解决C10k问题。 但是,在查看他们的数据库包装器时,我遇到了以下代码:

def _execute(self, cursor, query, parameters):
    try:
        return cursor.execute(query, parameters)
    except OperationalError:
        logging.error("Error connecting to MySQL on %s", self.host)
        self.close()
        raise
据我所知,对于构建在libmysqlclient之上的MySQLdb调用是阻塞的。 如果存在长时间运行的查询,我的理解是整个Tornado服务器将无响应直到查询完成,除非有一些神奇的代码实现了异步机制。

2
你期望什么?非阻塞并不意味着“所有行都同时运行”。 - zneak
6
接受错误答案应该得到-1的分数惩罚;非阻塞的Web服务器不应该因为其他请求需要访问数据库(磁盘)而阻塞请求。 - Glenn Maynard
1
感谢您的评论,但我相信我接受了回答我的问题的答案:使用MySQL包装器会使整个服务器阻塞吗?答案似乎是:是的。Tornado没有提供一个进程池来与MySQL通信,因此它会阻塞。您的答案也很有道理,但Nicholas先到了。 - ipartola
4个回答

33
如果你在顶部编写非阻塞代码,如使用asyncmongo@tornado.web.asynchronous装饰器,则Tornado是非阻塞的框架。作为框架,Tornado提供了相关工具。
其中一位原始作者Bret Taylor在文章中写道:
我们尝试了不同的异步数据库方法,但由于通常情况下,如果我们的数据库查询正在积压请求,则我们的后端无法承受负载。而对于足够缓慢的事情,我们会通过异步HTTP模块异步地获取抽象成单独的后端服务。
确实,Tornado不包括非阻塞数据库层;实际上,与例如Django的ORM不同,数据库层根本不是Tornado框架的组成部分。是的,Tornado有一个阻塞的MySQL包装器,因为FriendFeed正好使用它,但这更像是外部库而不是核心功能。我相信大多数人都在使用其他东西来访问数据库。

15

是的,在没有其他措施的情况下,服务器将等待查询完成执行。这并不意味着Tornado不是非阻塞Web服务器。

“非阻塞Web服务器”不会在网络I/O上阻塞(如果它进行静态文件服务,则可能具有某些磁盘I/O的规定)。这并不意味着您的应用程序可以获得即时的、违反因果关系的指令执行。

执行数据库调用需要时间,就像读取文件、格式化字符串、处理模板等操作也需要时间。在与服务器的主事件循环相同的线程中执行任何这些操作都会阻止循环继续进行,直到完成为止。


1
感谢您的快速回复。我理解非阻塞是指在一个请求等待处理时,另一个请求正在被处理,因为Web服务器的操作是异步的。但是,在这种情况下,如果有9,999个用户请求半静态页面,而只有一个用户请求长时间运行的查询页面,则这9,999个用户将不得不等待这一个用户。 - ipartola
如果我想在Web应用程序中实现非阻塞的数据库访问,我该如何使用Tornado实现呢? - Chetan
你不需要这样做,你只需添加更多Tornado实例并在它们之间进行负载均衡。你的数据库查询不应该需要那么长时间,否则就意味着存在一些其他的设计和/或操作问题。 - z8000
或者您可以使用异步接口和更加并发友好的数据库,如asyncmongo或者motor,与MongoDB一起使用。 - gaborous
我能否通过Python线程以某种方式实现多个任务的并行执行? - remort

1

Tornado 是非阻塞的,但只限于一些像读写 socket 文件这样的 IO 操作。

如果你希望代码中的所有内容都是非阻塞的,那么你就必须自己设计。但如果你的代码计算密集型,那么非阻塞对你来说是没有意义的。在这种情况下,你可以使用多进程。

记住一件事:非阻塞只意味着服务器发送/接收数据时不会阻塞。如果你无法使你的代码非阻塞,那么你的整个应用程序就会在某种程度上被阻塞。


0

是的,这并不是一个完全非阻塞的Web服务器。

非阻塞Web服务器使用非阻塞API进行文件I/O、数据库访问等操作,以确保一个需要等待某些操作完成的请求不会阻止其他请求的处理。这适用于可能阻塞服务器的所有操作,包括数据库访问。

没有什么比非阻塞数据库访问更愚蠢的了,这样做非常合理,可以运行与一个请求相关的非阻塞查询,并在此过程中处理其他请求。实际上,这通常意味着对数据库后端进行多个连接。

请注意,如果您尝试运行一万个并发请求,请小心:大多数数据库后端无法处理这种情况。如果您有超过几十个数据库请求需要并行运行,您可能需要像连接池一样的东西,以允许Web服务器建立大量的数据库连接而不会淹没后端。这将导致请求被阻塞,在队列中等待获取数据库访问权限,但通过这种方式进行操作,它不会阻塞整个服务器,只会阻塞需要数据库的请求。


15
你正在谈论你并不完全理解的东西。Tornado Web服务器是非阻塞的。如果你选择使用Tornado框架对MySQLdb的可选轻量级包装器,你可能会损失非阻塞Web服务器的优势,但这并不影响Web服务器本身,因为数据库模块并不属于Web服务器的一部分。 - Nicholas Knight
@Nicholas Knight:不,我完全理解“非阻塞式Web服务器框架”(重新阅读原帖)的含义;显然,你并不理解。 - Glenn Maynard

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接