Tornado
Tornado是使用Python编写的一个强大的、可扩展的Web服务器。它在处理严峻的网络流量时表现得足够强健,但却在创建和编写时有着足够的轻量级,并能够被用在大量的应用和工具中。
我们现在所知道的Tornado是基于Bret Taylor和其他人员为FriendFeed所开发的网络服务框架,当FriendFeed被Facebook收购后得以开源。不同于那些最多只能达到10,000个并发连接的传统网络服务器,Tornado在设计之初就考虑到了性能因素,旨在解决C10K问题,这样的设计使得其成为一个拥有非常高性能的框架。此外,它还拥有处理安全性、用户验证、社交网络以及与外部服务(如数据库和网站API)进行异步交互的工具。
C10K问题
基于线程的服务器,如Apache,为了传入的连接,维护了一个操作系统的线程池。Apache会为每个HTTP连接分配线程池中的一个线程,如果所有的线程都处于被占用的状态并且尚有内存可用时,则生成一个新的线程。尽管不同的操作系统会有不同的设置,
大多数Linux发布版中都是默认线程堆大小为8MB。Apache的架构在大负载下变得不可预测,为每个打开的连接维护一个大的线程池等待数据极易迅速耗光服务器的内存资源。
大多数社交网络应用都会展示实时更新来提醒新消息、状态变化以及用户通知,这就要求客户端需要保持一个打开的连接来等待服务器端的任何响应。这些长连接或推送请求使得Apache的最大线程池迅速饱和。一旦线程池的资源耗尽,服务器将不能再响应新的请求。
异步服务器在这一场景中的应用相对较新,但他们正是被设计用来减轻基于线程的服务器的限制的。当负载增加时,诸如Node.js,lighttpd和Tornodo这样的服务器使用协作的多任务的方式进行优雅的扩展。
也就是说,如果当前请求正在等待来自其他资源的数据(比如数据库查询或HTTP请求)时,一个异步服务器可以明确地控制以挂起请求。异步服务器用来恢复暂停的操作的一个常见模式是当合适的数据准备好时调用回调函数。
快速入手
1、安装Tornado
pip install tornado
源码安装:https://pypi.python.org/packages/source/t/tornado/tornado-4.3.tar.gz
2、第一个Tornado程序
#!/usr/bin/env python#-*- coding:utf-8 -*-
__author__ = 'luotianshuai'
importtornado.ioloopimporttornado.webclassMainHandler(tornado.web.RequestHandler):defget(self):
self.write("Hello, world")
application=tornado.web.Application([
(r"/index", MainHandler),
])if __name__ == "__main__":
application.listen(8888)
tornado.ioloop.IOLoop.instance().start()
基本上所有的WEB框架都有以下的流程(以Tornado为例):
准备阶段
加载配置文件
加载路由映射 application = tornado.web.Application([(r"/index", MainHandler),])
创建socket sk = socket
循环阶段
类似socket Server不断的循环监听文件句柄,当有请求过来的时候,根据用户的请求方法来来判断是什么请求,在通过反射来执行相应的函数或类
运行流程:
第一步:执行脚本,监听 8888端口
第二步:浏览器客户端访问/index --> http://127.0.0.1:8888/index
第三步:服务器接受请求,并交由对应的类处理该请求
第四步:类接受到请求之后,根据请求方式(post/ get /delete ...)的不同调用并执行相应的方法
第五步:方法返回值的字符串内容发送浏览器
3、application
application =tornado.web.Application([
(r"/index", MainHandler),
])
内部在执行的时候执行了两个方法__init__方法和self.add_handlers(".*$", handlers)方法{源码后期解析Tornado时补充}
这个add_handlers默认传输的".*$" 就是www,他内部生成的路由映射的时候相当于(二级域名的方式)下图:
我们可以通过application.add_handlers,添加一个“shuaige.com”,他会生成一个类似下面的对应关系
shuaige
.*
如果匹配的是shuaige他会去"shuaige"里去找对应关系,如果没有匹配默认就去.*,他这个就类似Django中的URL分类!~~
application =tornado.web.Application([
(r"/index", MainHandler),
])
application.add_handlers("shuaige.com",([
(r"/index", MainHandler),
])
)
路由系统其实就是 url 和 类 的对应关系,这里不同于其他框架,其他很多框架均是 url 对应 函数,Tornado中每个url对应的是一个类。
#!/usr/bin/env python#-*- coding:utf-8 -*-
__author__ = 'luotianshuai'
importtornado.ioloopimporttornado.webclassMainHandler(tornado.web.RequestHandler):defget(self):
self.write("Hello, world")classShuaige(tornado.web.RedirectHandler):defget(self):
self.write("This is shuaige web site,hello!")
application=tornado.web.Application([
(r"/index", MainHandler),
])
application.add_handlers("shuaige.com",([
(r"/index", Shuaige),
])
)if __name__ == "__main__":
application.listen(8888)
tornado.ioloop.IOLoop.instance().start()
模板
Tornao中的模板语言和django中类似,模板引擎将模板文件载入内存,然后将数据嵌入其中,最终获取到一个完整的字符串,再将字符串返回给请求者。
Tornado 的模板支持“控制语句”和“表达语句”,控制语句是使用 {% 和 %} 包起来的 例如 {% if len(items) > 2 %}。表达语句是使用 {{和 }}包起来的,例如 {{ items[0] }}。
控制语句和对应的 Python 语句的格式基本完全相同。我们支持 if、for、while 和 try,这些语句逻辑结束的位置需要用 {% end %} 做标记。还通过 extends 和 block 语句实现了模板继承。这些在 template 模块 的代码文档中有着详细的描述。
目录结构:
Tornado主文件:
#!/usr/bin/env python#-*- coding:utf-8 -*-
importtornado.ioloopimporttornado.webclassMainHandler(tornado.web.RequestHandler):defget(self):
self.render('index.html')
settings={'template_path': 'template','static_path': 'static','static_url_prefix': '/static/',
}
application=tornado.web.Application([
(r"/index", MainHandler),
],**settings)if __name__ == "__main__":
application.listen(8888)
tornado.ioloop.IOLoop.instance().start()
主模板html(layout.html)
shuaige{% block css%}{% end %}