tornado recipe
for me
1,tornado是一个单进程http server(当然也支持wsgi)
所以不需要web server来处理http协议,web server直接作为proxy转发即可。
一般根据服务器的core数目来决定启动几个tornado进程(bind在不同的端口上)。
httpserver.py中的_on_headers(),硬编码来处理http请求(http协议的科普备忘看这里:http://roclinux.cn/?p=3450)。
2,异步io
对外展现往往是callback模式,内部实现用io复用机制来进行event通知。
@tornado.web.asynchronous时不立即进行http应答,从而达到long polling效果。
管理大量慢连接,利用了epoll,这里有一篇对epoll event的注解:
http://hi.baidu.com/soulshape/item/0c7e00c0866e207488ad9ee5
特别留意EPOLLRDHUP。
python示例:http://scotdoyle.com/python-epoll-howto.html
其中example4展示了ET模式下的注意点:
a,w/r直到全部结束为止,否则下次无法感知;
b,留意w时可以通过buf避免sock_write堵塞:http://www.cnblogs.com/OnlyXP/archive/2007/08/10/851222.html
不过检查了一下tornado和redis,用的都是LT模式。
3,chat demo
观察者模式,多个requery注册进来,重点是全局list中握着的是多个连接上的回调函数,所以就不用关心底层的sock了。
留意同一个类的不同对象的方法是可区分的:method bound on instance
>>> a.func <bound method A.func of <__main__.A instance at 0xb751c7cc>> >>> b.func <bound method A.func of <__main__.A instance at 0xb751c88c>> >>> id(a.func) 3075798876L >>> id(b.func) 3075798876L >>> a.func == b.func False >>> hash(a.func) 3389 >>> hash(b.func) 3529
顺便再科普一下set:The elements of a set must be hashable。
4,tornado.gen
避免逻辑被各种onXXX callback切割的支离破碎。
from tornado.platform.caresresolver import CaresResolver from tornado import gen import tornado.ioloop @gen.coroutine def resolver(): resolver = CaresResolver() result = yield resolver.resolve('baidu.com',80) //不会阻塞住进程,其他event可以得到响应。 print(result) tornado.ioloop.IOLoop.instance().stop() resolver() tornado.ioloop.IOLoop.instance().start()
不过不是很好理解。。。也可以老老实实用callback。
leave a comment