news 2026/5/2 20:27:25

python tornado

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
python tornado

# 聊聊Tornado:一个被低估的Python异步框架

它到底是什么

Tornado,本质上是一个用Python写的非阻塞式Web服务器框架。说到这个问题,得从开发者面临的一个实际困境说起。

去年我帮一个朋友重构他的爬虫服务,用的是Flask跑在Gunicorn上。平时运行得挺好,可一旦遇到某个网站突然返回一堆慢响应,整个服务就开始卡死——不是CPU不够,而是所有工作线程都被堵在那儿等I/O。你想想看,一个线程在等待远程服务器的响应,什么事情都做不了。

这就是Tornado要解决的根本问题。它用一种事件循环的机制,替代了传统的线程或进程模型。简单来说,当你的代码在等某个网络请求返回时,Tornado不会傻傻地在那里干等,而是去处理其他请求。等那个网络请求的数据到了,它会回过来继续处理。

有人可能会说,这不就是异步吗?Python 3里不是有asyncio吗?没错,但Tornado从2010年左右就开始这么做了,比asyncio早了好多年。它的核心——ioloop模块,是一个完整的事件循环实现,可以和asyncio协同工作,但并不依赖它。

它真正擅长什么

Tornado的用武之地,主要集中在需要处理大量并发连接的场景。

拿长轮询来说。想象你在做个即时通讯功能,用户打开网页,需要实时接收新消息。传统做法是让客户端每隔几秒发个请求问“有没有新消息?”。这太傻了——多数情况下服务器根本没新消息,白白浪费带宽和资源。长轮询的做法是,客户端发一个请求,服务器把这个请求挂在那里,直到有新消息了才返回。这样做,一个客户端就会有一个长时间挂起的连接。

如果用户有1万人同时在线,那就是1万个并发连接。这在Flask这类同步框架上几乎是灾难,每个连接需要一个线程,1万个线程的内存消耗和上下文切换成本就够你受的。但在Tornado里,1万个连接只是一个事件循环里维护的1万个socket对象,完全不是一个数量级。

除此之外,WebSocket也是Tornado的强项。很多框架的WebSocket支持像是后来硬加上去的,而Tornado在设计之初就考虑到了双向通信的需求。你可以在同一个应用里,同时处理HTTP请求和WebSocket连接,共享相同的身份验证和逻辑。

怎么开始用它

用Tornado写个简单的服务,比大部分框架都直接。

importtornado.ioloopimporttornado.webclassMainHandler(tornado.web.RequestHandler):defget(self):self.write({"message":"Hello, World!"})defmake_app():returntornado.web.Application([(r"/",MainHandler),])if__name__=="__main__":app=make_app()app.listen(8888)tornado.ioloop.IOLoop.current().start()

这段代码启动后,会直接监听8888端口,完全不需要额外的WSGI服务器。Tornado本身就是个完整的HTTP服务器。

但要注意,上面这个例子里的get方法是同步的。如果在这里面做耗时操作,比如查询数据库或调用外部API,它还是会阻塞事件循环。正确的做法是使用异步方法:

classAsyncHandler(tornado.web.RequestHandler):asyncdefget(self):# 假设有个异步的HTTP客户端http_client=tornado.httpclient.AsyncHTTPClient()response=awaithttp_client.fetch("https://api.example.com/data")self.write(response.body)

这里用了async/await关键字,让Tornado知道这个方法在执行到await的时候可以切出去做别的事。

一些实际经验

用Tornado这几年,有几点体会特别深。

第一,别把所有事情都做成异步的。Tornado的异步模型很棒,但Python本身没有真正的多核并行能力。如果你的业务逻辑里有CPU密集型的计算,比如图片处理、数据压缩,这些事不应该放在主事件循环里。正确做法是用tornado.process模块里提供的子进程机制,或者直接丢给Celery去处理。

第二,数据库连接池是个容易被忽略的坑。很多ORM的连接池是线程安全的,但不一定适用于协程环境。在Tornado里用SQLAlchemy需要特别注意,最好用create_async_engine(SQLAlchemy 1.4之后支持的异步版本)。如果非要用同步的数据库驱动,就得把数据库操作封装成run_in_executor调用,这会失去一些性能优势。

第三,也是很多人会踩的坑:不要在RequestHandler里持有长时间的引用。Tornado会复用这些handler对象,如果某个handler里的回调持有了它的引用,这个对象就永远无法被垃圾回收,相当于内存泄漏。实际中见过一个项目,因为代码里不小心把self传进了另一个协程,结果内存涨到十几个G。

和其他框架的比较

说到Flask,它和Tornado面对的场景几乎完全不同。Flask追求的是简单、优雅,开发者写个API可以很快上手,学习曲线几乎为零。但它根本上是个同步框架,部署时得靠Gunicorn这类WSGI服务器撑起并发。遇到长连接或WebSocket场景,Flask就比较吃力了,虽然可以通过插件支持,但体验和Tornado的“原生支持”还是有差距。

FastAPI是近几年比较火的框架。它在性能上做了很多优化,底层依赖Starlette和asyncio。FastAPI的强项在于类型提示、自动生成API文档,这些Tornado确实比不上。但FastAPI的WebSocket支持更像是在HTTP框架上“打了补丁”,而Tornado的设计从一开始就考虑了这个需求。如果要做复杂的实时通信系统,Tornado在可靠性和代码组织上往往更合适。

Django则是另一个维度的东西。它是一个全栈框架,自带ORM、Admin后台、模板引擎。Tornado几乎不做这些事,它更像个工具箱。用Django做大型CMS类项目很顺手,但如果主要需求是处理超高并发的WebSocket连接,Django的同步本质和大型框架的启动开销会成为拖累。

有一点很多人不知道,Tornado被很多大公司的关键组件采用。比如Facebook(Tornado最初就是他们开发的,不过在Facebook内部用C++重写了一个版本),还有ZMQ的官方Python库Czmq的异步接口就用到了Tornado。这些场景对稳定性和性能都有苛刻要求,说明Tornado在这些方面经得起考验。

我的看法是,如果你明确需要高并发、长连接、WebSocket这类特性,直接选Tornado;如果只是写个普通的Web API,Flask或FastAPI可能更顺手。没必要为了用Tornado而用Tornado,毕竟它的同步编码的方式确实增加了代码复杂度。

最后说个有意思的现象。从前段时间开始,Python社区似乎又对Tornado的关注度上升了。原因可能是微服务和消息驱动的架构越来越普及,服务之间的通信量越来越大,长连接的需求也越来越多。Tornado这种“铁了心为高并发而生”的框架,又开始展现出它的价值。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/2 20:12:27

FastAPI+Pydantic+MongoDB构建现代化Python后端API样板工程

1. 项目概述:一个现代Python后端API的样板工程最近在梳理团队内部的后端技术栈,发现很多新启动的项目在基础架构搭建上花费了太多重复劳动。大家一上来就纠结于框架选型、数据库连接、数据验证、API文档生成这些基础却又繁琐的环节,每个项目都…

作者头像 李华
网站建设 2026/5/2 20:09:27

视觉世界建模:多模态AI推理的核心技术解析

1. 视觉世界建模:多模态推理的新范式在人工智能领域,多模态模型正逐渐突破单一模态的限制,展现出接近人类认知的推理能力。这种能力的核心在于视觉世界建模(Visual World Modeling)技术——它让AI系统能够像人类一样&a…

作者头像 李华
网站建设 2026/5/2 20:06:29

人工智能篇---信号与系统、通信原理和深度学习的关系

信号与系统、通信原理和深度学习的关系,本质上是一种方法论上的双向奔赴: 传统方向(信通→深度学习):通信和信号处理几十年来积累的数学工具,如傅里叶变换、卷积、信息论,为深度学习提供了现成的…

作者头像 李华
网站建设 2026/5/2 20:05:45

多环境部署场景:Mem Reduct内存管理工具的专业配置策略

多环境部署场景:Mem Reduct内存管理工具的专业配置策略 【免费下载链接】memreduct Lightweight real-time memory management application to monitor and clean system memory on your computer. 项目地址: https://gitcode.com/gh_mirrors/me/memreduct M…

作者头像 李华