Tornado是很优秀的非阻塞式服务器,我们一般用它来写Web 服务器,据说知乎就是用Tornado写的。 

 

如果对tornado源码不是很了解,可以先看一下另一篇文章:

http://yunjianfei.iteye.com/blog/2185476

 

通过详细阅读理解Tornado的源码,你将会获得以下收获:

1. 这是一个绝佳的学习python的机会,你会接触到generator/yield , with statment, functools.partial,  concurrent.futures 等等很多平时较少接触到的只是

2. 可以更好的通过tornado来编写异步Server以及client

3. 更好的理解epoll,ET/LT相关知识

 

本文可以协助更好的去阅读理解tornado的源码,提供一个跟踪理解源码的思路和顺序。

 

从一个例子开始

 

注意:在源码跟踪过程中,一共有51个步骤,请务必按照步骤,打开你手中对应的源码,进行跟踪分析。

 

以下是一个异步客户端的例子,作用是获取www.baidu.com首页的内容。那么开始我们的源码跟踪之旅。

在开始跟踪前,请准备好tornado源码,本文中的源码均只截取了部分关键性的代码。

 

文件名: async.py

 

#!/usr/bin/env python2.7  
# -*- coding: utf-8 -*-  
from tornado import ioloop, httpclient, gen  
from tornado.gen import Task  
import pdb, time, logging  
#Init logging  
def init_logging():  
    logger = logging.getLogger()  
    logger.setLevel(logging.DEBUG)  
    sh = logging.StreamHandler()  
    formatter = logging.Formatter('%(asctime)s -%(module)s:%(filename)s-L%(lineno)d-%(levelname)s: %(message)s')  
    sh.setFormatter(formatter)  
  
    logger.addHandler(sh)  
    logging.info("Current log level is : %s", logging.getLevelName(logger.getEffectiveLevel()))  
  
init_logging()  
  
#pdb.set_trace()  
 
@gen.coroutine #注意这里是一个装饰器,是实现异步client的关键  
def download(url):  
    http_client = httpclient.AsyncHTTPClient()  
  
    #6. 执行http_client.fetch(url),然后退出download函数,等待下次步骤5中的gen.next或者gen.send调用  
    #51. 获取从www.baidu.com返回的响应,赋值给response  
    response = yield http_client.fetch(url)   
    print 'response.length =', len(response.body)  
    ioloop.IOLoop.instance().stop()  
  
future = download("http://www.baidu.com/")  #0. 开始源码分析  
print future  
logging.info("****start ioloop*************")  
ioloop.IOLoop.instance().start() #18. 启动ioloop  

注意 :这里4.4x有修改:

在async.py 23行实例化
http_client = httpclient.AsyncHTTPClient()  

我们看到继承了Configurable 详细看我的IOLoop实例化图
class AsyncHTTPClient(Configurable):
    
    
    def __new__(cls) #实例化之前先执行
        super(AsyncHTTPClient,cls).__new__ 执行基类的new
而基类中也会执行configurable_default 
这里返回的是        return SimpleAsyncHTTPClient
这个类
所以上面的http_client其实是SimpleAsyncHTTPClient的对象

所以找方法从其开始找
fetch_impl

其实例化时候直接封装了下面的返回结果 后面会用到OverrideResolver   resolve方法
self.resolver = OverrideResolver(resolver=self.resolver,
                                             mapping=hostname_mapping)

    def resolve(self, host, port, *args, **kwargs):
        if (host, port) in self.mapping:
            host, port = self.mapping[(host, port)]
        elif host in self.mapping:
            host = self.mapping[host]
        return self.resolver.resolve(host, port, *args, **kwargs)
4.4.x的改动

 

 

 

相关文章:

  • 2021-11-09
  • 2021-09-01
  • 2022-12-23
  • 2022-12-23
  • 2021-11-20
  • 2021-05-21
猜你喜欢
  • 2022-12-23
  • 2021-11-11
  • 2021-06-20
  • 2022-01-07
  • 2021-09-09
  • 2022-03-11
  • 2022-01-25
相关资源
相似解决方案