19

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

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

据我所知,对建立在 之上的 MySQLdb 的调用libmysqlclient阻塞的。

我是否认为长时间运行的查询会导致整个 Tornado 服务器在完成之前无响应,或者代码中有魔法吗?

4

4 回答 4

33

如果您在顶部编写非阻塞代码,则 Tornado 是非阻塞的,例如。使用asyncmongo@tornado.web.asynchronous装饰器。Tornado 作为一个框架为此提供了工具。

Bret Taylor,原作者之一,写道

我们尝试了不同的异步 DB 方法,但在 FriendFeed 选择了同步,因为通常如果我们的 DB 查询积压了我们的请求,我们的后端无论如何都无法适应负载。足够慢的东西被抽象为分离后端服务,我们通过异步 HTTP 模块异步获取这些服务。

Tornado 确实不包含非阻塞数据库层。事实上,数据库层根本不是 Tornado 框架的组成部分,这与 Django 的 ORM 不同。是的,Tornado 附带了阻塞 MySQL 包装器,因为这正是 FriendFeed 碰巧使用的,但它更像是一个外部库而不是核心功能。我很确定大多数人都在使用其他东西来访问数据库。

于 2011-01-25T08:27:55.050 回答
15

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

“非阻塞 Web 服务器”不会阻塞网络 I/O(如果它提供静态文件服务,可能会为磁盘 I/O 提供一些规定)。这并不意味着您可以在应用程序中立即执行违反因果关系的指令。

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

于 2010-09-03T19:24:00.243 回答
1

Tornado 是非阻塞的,但仅限于一些 IO 操作,例如读取或写入套接字文件。

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

记住一件事非阻塞只是意味着服务器发送/接收日期不会阻塞。如果你不能让你的代码非阻塞,那么你的整个应用程序就会阻塞。

于 2018-06-18T15:01:25.887 回答
0

是的; 这根本不是一个完全无阻塞的 Web 服务器。

非阻塞网络服务器不会阻塞,使用非阻塞 API 进行文件 I/O、数据库访问等,以确保一个必须等​​待某事完成的请求不会阻止其他请求的处理. 这适用于可能阻止服务器的所有内容,包括数据库访问。

在非阻塞数据库访问中没有什么比“违反因果关系”更愚蠢的了。运行与一个请求相关的非阻塞查询并在该请求仍在运行时处理其他请求是非常有意义的。在实践中,这通常意味着与数据库后端建立多个连接。

请注意,如果您尝试运行一万个并发请求,请注意:大多数数据库后端无法处理此问题。如果您有几十个数据库请求要并行运行,您可能需要连接池之类的东西,以允许 Web 服务器在不占用后端的情况下建立大量数据库连接。这将导致请求阻塞,在队列中等待获取数据库访问,但这样做意味着它不会阻塞整个服务器——只是需要数据库的请求。

于 2010-09-03T23:20:16.503 回答