Tornado真的是非阻塞的吗?

19 投票
4 回答
10571 浏览
提问于 2025-04-16 03:41

Tornado自称是“一个相对简单的非阻塞网络服务器框架”,它的设计目的是为了解决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 个回答

1

Tornado是非阻塞的,但这仅限于一些输入输出操作,比如对套接字文件的读写。

如果你想让代码中的所有操作都变成非阻塞的,那就得自己设计。不过,如果你的代码是计算密集型的,那么非阻塞就没什么意义了。在这种情况下,你可能需要使用多进程。

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

33

Tornado是一个非阻塞的框架,如果你在上面写非阻塞的代码,比如使用asyncmongo@tornado.web.asynchronous这个装饰器。Tornado这个框架提供了这样的工具。

其中一位原作者Bret Taylor在写道

我们尝试了不同的异步数据库方法,但最终在FriendFeed选择了同步方式,因为如果我们的数据库查询导致请求积压,我们的后端根本无法应对这种负载。那些速度比较慢的操作被抽象成了独立的后端服务,我们通过异步HTTP模块来获取这些服务。

确实,Tornado并没有包含一个非阻塞的数据库层;实际上,数据库层根本不是Tornado框架的核心部分,这和Django的ORM是不同的。是的,Tornado附带了一个阻塞的MySQL封装,因为FriendFeed正好使用了这个,但这更像是一个外部库,而不是核心功能。我相信大多数人使用的数据库访问方式都是其他的。

15

是的,如果没有其他措施,服务器会等查询执行完毕。这并不意味着Tornado就不是一个非阻塞的网络服务器。

所谓“非阻塞网络服务器”,就是在处理网络输入输出时不会被卡住(如果它提供静态文件服务,可能在磁盘输入输出上也会有一些处理)。这并不意味着你的应用程序里的指令会立刻执行,或者会打破因果关系。

进行数据库调用是需要时间的,就像读取文件、格式化字符串、处理模板等操作也需要时间一样。如果在服务器的主事件循环的同一个线程中做这些事情,就会导致事件循环停下来,直到你完成这些操作。

撰写回答