玩蛇记-使用tornado构建高性能Web应用

From: http://www.cnblogs.com/Alexander-Lee/archive/2010/03/20/1690292.html


这个新系列是为了记录在python下的工作点滴,最近从微软平台突然转换到了linux平台下工作,于是.NET不怎么排得上用场,且在python下工作多日才发现原来在.NET下的日子真是往事不堪回首月明中……当然仅仅是一家之言,纯属个人感受。总之呢,玩蛇记这个系列就是用来专门记录python下工作的感想之用了。

在.NET下工作崇尚集成化,集成化的IDE,一体化的服务器,从操作系统到webserver,都是ms inside。非常适合初学者,啥都不用想,也没有太多让你选的。慢慢的能力提高了,就会觉得微软提供的东西不是那么完美,当你在开发的时候,很多东西如果不用微软内置的机制,就会让你费老大的力气去绕弯实现,比如DataGrid,很强大,但是大多数人都会在自己的blog离告诫后来者,还是回去用repeater吧,所见即所得的编辑器里面也因为各种为了妥协而加入的代码变得面目全非,直到后来的MVC的出现才勉强解决,不过以前在webform里积累的很多东西和技巧就付诸东流了。

在正式开篇前说了很多对.NET的不满,呵呵,小小偏题,幸亏博客园不是起点要按字数收钱。

话说回来,python很适合已经熟练掌握一种语言和平台的开发人员做拓展,比如已经熟练掌握java平台或者.NET的开发人员,当然更适合C和C++的开发人员来偶尔玩票一下Web开发。python好玩但并不是说它就是个漂亮的玩具,而是一种在linux,unix平台下非常具备生产力的语言。在很早的时候linux和bsd系统就默认内置python了,而现在很smart的ubuntu之类的很多集成的工具都是python编写的,而在web开发方面,估计是因为圈子小,而很多业余玩python的人大多不是正职搞Web开发的,所以国内用python开发Web的人不多。不过最近django之类的框架也出了书,虽然是沾了ROR的光,不过好歹也有人关注了。

其实python下最大的问题不是选择太少,恰恰是选择太多了,由于python的生产力实在是太强,要造个轮子的成本实在是很低,所以到处都是轮子,从Quixote,Django,web2py,web.py,karrigell……国内的还有uliweb……

绝对让你挑得眼花缭乱,也许是每个应用的需求各不相同,所以各个框架的出发点也各有分别,对初学者来说是眼花缭乱了,但是相对来说可选的范围也广了。还有一点和微软平台的区别就是,部署上也不是一体式的,IIS上架着.NET,这点其实是以前我非常眼热的。看着nginx,lighttpd这些新生代web server的让人心动的benchmark,再对比看着iis(那些标榜自己高performance的web server 在做对比测试的时候都不和iis一起比,不带一起玩的,不是一个等级……)

说到performance,我感觉自己有强烈的performance强迫症,看着跑得快的就眼热,所以就有了今天的猪脚-tornado,

这是一个facebook收购的一家叫friend feed的公司出品的框架,其实也是一款高性能的web server,纯python编写,开源,意味着我可以自己对其进行改进,且还有一个好处就是在文档异常缺乏的时候可以直接翻源码解决问题,事实证明这点非常有用,tornado的文档非常的缺乏,而且也没有api的说明,官网上的文档基本上等于就是把代码里的注释集中到了一起,不过还好python是如此的可爱,很多时候是靠着dir(object)来解决了问题。

由于facebook被和谐掉了,所以tornado的官网也未能幸免,其实python的下载页也被和谐掉了,不知道怎么回事,莫非是python.com造的孽?

祭上puff,直奔www.tornado.org,下载下来,解压,安装:

python setup.py install 

注意,必须在linux下安装,windows下没有epoll,所以用select代替了,非常的没效率,这点上twisted也是一般的光景。

由于tornado本身就是一个web server,所以自己就能单独运行。在用了2个星期后我感觉其实不安装,直接引用源码运行更好一些,很多时候可以方便自己对这个系统做点小改造。

安装后执行python,打开python shell,在其中输入 import tornado

回车后不报错就说明安装成功了

现在我们就可以用tornado来编写网站了,新建一个server.py

内容如下:

import tornado.httpserver
import tornado.ioloop
import tornado.web

class MainHandler(tornado.web.RequestHandler):
    def get(self):
        self.write("Hello, world")

application = tornado.web.Application([
    (r"/", MainHandler),
])

if __name__ == "__main__":
    http_server = tornado.httpserver.HTTPServer(application)
    http_server.listen(8888)
    tornado.ioloop.IOLoop.instance().start()

 

保存后,执行 python server.py

这个时候就能够通过浏览器看到 hello world的页面了

tornado和Django一样通过正则表达式的url mapping,不过有区别的是没有强制区分view和model,因为tornado虽然有一个简单的数据库封装,但是没有orm,幸好我对orm也不怎么感冒,且在python下orm确实也很鸡肋,而且真要用orm也能直接用现成的,真要自己写一个也很容易。模版系统也比较方便,不过没有集成Session,但是内部实现了一个安全cookie。不过现在很多系统都没用inproc的session了,所以就自己DIY了一个用memcached作为backend的Session出来。

这些东西我会在接下来的一系列POST里涉及到,因为没有写教程的打算,所以很多细节可能就点到即止了,更详细的相信愿意用这个玩意儿的也有这个能力去啃啃源代码,也就几千行。

另,tornado是一个单进程,单线程的Server,所以在每个RequestHandler的方法中的代码都是线程安全的。

很多人会有疑问,单进程单线程能快得快吗?其实事实胜于雄辩:

image

不过也由于这个特征,不能写一些延迟很大的操作,现在tornado暂时只支持用异步的curl,数据库操作暂时还是阻塞的,我正在研究增加一个异步的数据库操作模块来进一步提升其性能,如果有任何成果我会第一时间公布,也希望喜欢玩新鲜的蛇友同我交流

在上面的部分,我们创建了一个helloword的应用,并且能够通过浏览器访问它,这样我们就可以用Tornado来开发网站了,嗯,这是可喜的第一步,不过当你决定了用tornado开发网站,并且开始写新的handler的时候,你会发现需要频繁的,关掉,再重新启动服务器,这是一件非常让人抓狂的事情,我们需要在程序修改后,服务能够自动reload新的代码,和asp.net一样。但是tornado的文档实在是有限,在文档上找不到相关的任何说明。

但是山穷水尽疑无路柳暗花明又一村,无意在源代码里发现了一个autoreload.py的文件

image

猜想其实tornado是可以自己reload的,不过文档里没有说明,但是autoreload要怎么用呢。打开这个文件,看到其实里面很简单,只有两个函数,如下图

image

第二个函数是私有的,所以实际上start就是唯一的入口,我们在代码中发现,_reload_on_update函数其实在start中被作为一个回调函数注册到了io_loop中了,所以实际上我们只需要把ioloop传入start就可以实现autoreload了。所以将

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.instance().start()

 

这些代码改为:

def main():
    tornado.options.parse_command_line()
    application = tornado.web.Application([
        (r"/", MainHandler),
    ])
    http_server = tornado.httpserver.HTTPServer(application)
    http_server.listen(options.port)
    loop=tornado.ioloop.IOLoop.instance()
    tornado.autoreload.start(loop)
    loop.start()

这样子就行了。

注意,这里的reload只检测py文件的变动,如果是其他文件发生变动,比如css,图片这些,都不会引发reload。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值