tornado源码解析之IOLoop
admin
2023-07-31 00:46:18
0

0. 简介

tornado是一个用Python语言写成的Web服务器兼Web应用框架,由FriendFeed公司在自己的网站FriendFeed中使用,被Facebook收购以后框架以开源软件形式开放给大众。

tornado最大的特点就是其支持异步IO,所以它有着优异的性能。下表是和一些其他Web框架与服务器的对比:(处理器为 AMD Opteron, 主频2.4GHz, 4核) (来源wikipedia)

服务 部署 请求/每秒
Tornado nginx, 4进程 8213
Tornado 1个单线程进程 3353
Django Apache/mod_wsgi 2223
web.py Apache/mod_wsgi 2066
CherryPy 独立 785

先来看看hello world的例子。^_^

123456789101112131415161718192021222324252627 import tornado.httpserverimport tornado.ioloopimport tornado.optionsimport tornado.web from tornado.options import define, options define(\”port\”, default=8888, help=\”run on the given port\”, type=int)  class MainHandler(tornado.web.RequestHandler):    def get(self):        self.write(\”Hello, world\”)  def main():    tornado.options.parse_command_line()    application = tornado.web.Application([        (r\”/\”, MainHandler),    ])    http_server = tornado.httpserver.HTTPServer(application)    http_server.listen(options.port)    tornado.ioloop.IOLoop.current().start()  if __name__ == \”__main__\”:    main()

运行:

1 $ python3 helloworld.py

我们就得到一个web server监听在8888端口。用curl命令get一下,就返回了”Hello, world”。

tornado的代码结构可以在其官网了解,本文着重分析IOLoop的实现。

1. IOLoop

1.1 http交互的大致过程

介绍IOLoop之前我们先看看http server和http client交互的一个大致过程。

server端监听在某个端口,client端发送请求过来,server处理后返回,然后继续等待下一个请求,周而复始。如果用socket那一坨来描述的话就是:

123456789101112131415161718 1. server.py================================================================s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)s.bind(address)s.listen(backlog)While True:    connection = s.accept()    do_something()    connection.send()    connection.close()    2. client.py=================================================================s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)s.connect()s.send()s.recv()s.close()

1.2 聊聊阻塞与非阻塞

所谓阻塞,就是进程正在等待某些资源(如IO),而处于等待运行的状态(不占用CPU资源)。比如connect((“google.com”, 80))返回之前进程都是阻塞的,在它下面的语句得不到执行,除非connect返回。

很显然阻塞式的IO模型有个缺点就是并发量不大,试想如果server进程在do_something()处阻塞,而这时另外有个客户端试图连进来,则可能得不到响应。

提高并发量有几种实现方式:多线程(一个连接fork一个线程去处理);多进程(一个连接fork一个子进程去处理)(apache);事件驱动(nginx, epoll)等。tornado就是基于epoll(Linux)事件驱动模型实现的。

当然它们有各自的优缺点,此文不详述,有兴趣的读者可以自行google之。^_^

关于IO模型,epoll, 同步,异步,阻塞,非阻塞的概念,可以参考这两篇文章:
https://segmentfault.com/a/11…

http://blog.csdn.net/historya…

1.3 IOLoop实现

1.3.1 IOLoop配置

前文说到tornado是基于epoll事件驱动模型,也不完全正确,tornado实际上是根据平台选择底层驱动。请看IOLoop类的configurable_default方法:

1234567891011   @class gn: justify\”>tornado最大的特点就是其支持异步IO,所以它有着优异的性能。下表是和一些其他Web框架与服务器的对比:(处理器为 AMD Opteron, 主频2.4GHz, 4核) (来源wikipedia)

服务 部署 请求/每秒
Tornado nginx, 4进程 8213
Tornado 1个单线程进程 3353
Django Apache/mod_wsgi 2223
web.py Apache/mod_wsgi 2066
CherryPy 独立 785

先来看看hello world的例子。^_^

123456789101112131415161718192021222324252627 import tornado.httpserverimport tornado.ioloopimport tornado.optionsimport tornado.web from tornado.options import define, options define(\”port\”, default=8888, help=\”run on the given port\”, type=int)  class MainHandler(tornado.web.RequestHandler):    def get(self):        self.write(\”Hello, world\”)  def main():    tornado.options.parse_command_line()    application = tornado.web.Application([        (r\”/\”, MainHandler),    ])    http_server = tornado.httpserver.HTTPServer(application)    http_server.listen(options.port)    tornado.ioloop.IOLoop.current().start()  if __name__ == \”__main__\”:    main()

运行:

1 $ python3 helloworld.py

我们就得到一个web server监听在8888端口。用curl命令get一下,就返回了”Hello, world”。

tornado的代码结构可以在其官网了解,本文着重分析IOLoop的实现。

1. IOLoop

1.1 http交互的大致过程

介绍IOLoop之前我们先看看http server和http client交互的一个大致过程。

server端监听在某个端口,client端发送请求过来,server处理后返回,然后继续等待下一个请求,周而复始。如果用socket那一坨来描述的话就是:

123456789101112131415161718 1. server.py================================================================s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)s.bind(address)s.listen(backlog)While True:    connection = s.accept()    do_something()    connection.send()    connection.close()    2. client.py=================================================================s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)s.connect()s.send()s.recv()s.close()

1.2 聊聊阻塞与非阻塞

所谓阻塞,就是进程正在等待某些资源(如IO),而处于等待运行的状态(不占用CPU资源)。比如connect((“google.com”, 80))返回之前进程都是阻塞的,在它下面的语句得不到执行,除非connect返回。

很显然阻塞式的IO模型有个缺点就是并发量不大,试想如果server进程在do_something()处阻塞,而这时另外有个客户端试图连进来,则可能得不到响应。

提高并发量有几种实现方式:多线程(一个连接fork一个线程去处理);多进程(一个连接fork一个子进程去处理)(apache);事件驱动(nginx, epoll)等。tornado就是基于epoll(Linux)事件驱动模型实现的。

当然它们有各自的优缺点,此文不详述,有兴趣的读者可以自行google之。^_^

关于IO模型,epoll, 同步,异步,阻塞,非阻塞的概念,可以参考这两篇文章:
https://segmentfault.com/a/11…

http://blog.csdn.net/historya…

1.3 IOLoop实现

1.3.1 IOLoop配置

前文说到tornado是基于epoll事件驱动模型,也不完全正确,tornado实际上是根据平台选择底层驱动。请看IOLoop类的configurable_default方法:

1234567891011   @class ethod    def configurable_default

相关内容

热门资讯

Mobi、epub格式电子书如... 在wps里全局设置里有一个文件关联,打开,勾选电子书文件选项就可以了。
500 行 Python 代码... 语法分析器描述了一个句子的语法结构,用来帮助其他的应用进行推理。自然语言引入了很多意外的歧义,以我们...
定时清理删除C:\Progra... C:\Program Files (x86)下面很多scoped_dir开头的文件夹 写个批处理 定...
scoped_dir32_70... 一台虚拟机C盘总是莫名奇妙的空间用完,导致很多软件没法再运行。经过仔细检查发现是C:\Program...
65536是2的几次方 计算2... 65536是2的16次方:65536=2⁶ 65536是256的2次方:65536=256 6553...
小程序支付时提示:appid和... [Q]小程序支付时提示:appid和mch_id不匹配 [A]小程序和微信支付没有进行关联,访问“小...
pycparser 是一个用... `pycparser` 是一个用 Python 编写的 C 语言解析器。它可以用来解析 C 代码并构...
微信小程序使用slider实现... 众所周知哈,微信小程序里面的音频播放是没有进度条的,但最近有个项目呢,客户要求音频要有进度条控制,所...
Apache Doris 2.... 亲爱的社区小伙伴们,我们很高兴地向大家宣布,Apache Doris 2.0.0 版本已于...
python清除字符串里非数字... 本文实例讲述了python清除字符串里非数字字符的方法。分享给大家供大家参考。具体如下: impor...