• Python Web服务高并发框架【1】(Tornado)


    本节学习目标:

     (1)了解Tornado的特点
     (2)了解Tornado工作流程
     (3)掌握Tornado在Window及Linux中的安装
     (4)理解同步、异步
     (5)协程基础编程
    

    本节课程内容:

    一、Tornado介绍

    Tornado是使用Python编写的一个强大的可扩展的Web服务器。除了FriendFeed和Facebook外,还有很多公司在生产上转向Tornado,包括Quora、Turntable.fm、Bit.ly及MyYearbook等。

    相对于其它Python的网络框架,Tornado有如下特点:

    • 完备的Web框架:与Django、Flask框架等一样,Tornado也提供了URL路由映射、Request上下文、基于模板引擎的页面渲染技术等开发Web应用的必备工具。
    • 非阻塞式服务器且速度相当快:tornado每秒可以处理数以千计的连接,其得利于非阻塞的方式和对epoll的运用。
    • 高效的网络库:其性能可以与Twisted、Gevent等底层Python框架相媲美,提供了异步I/O支持、超时时间处理。这使得Tornado除了可以作为web服务器框架,还可以用来做爬虫应用、物联网网关、游戏服务器等后台应用。
    • 提供高效HTTPClient:除了服务器端框架,tornado还提供了基于异步框架的HTTP客户端。
    • 提供高效的内部HTTPServer:虽然其他Python网络框架(Django、Flask)也提供了内部HTTP服务器,但他们由于性能原因只能用于测试环境。而tornado的HTTPServer与tornado异步调用紧密结合,可以直接用于生成环境。
    • 完备的WebSocket支持WebSocket是HTML5的一种新标准,实现了浏览器和服务器之间的双向实时通信。
      根据以上特点

    Tornado常被用作大型站点的接口服务框架,而不像Django那样着眼于建立完整的大型网站。除此之外,Tornado还常用于异步及协程编程、身份认证框架、独特的非WSGI部署方式等等。

    二、Tornado工作流程图

    三、安装Tornado

    Tornado已经被配置到PyPI中,在Windows和Linux中都可以通过一条pip命令完成安装
    #pip install tornado
    该条命令运行在Linux操作系统中。安装结果如下图所示:
    安装(tornado).png

    四、同步/异步及yield

    协程是Tornado中推荐的变成方式,使用协程可以开发出简捷、高效的异步处理代码。首先要掌握的内容是:
    (1) 同步I/O和异步I/O

    • 同步I/O(synchronous Input/Output operation):
        导致请求进程阻塞,直到I/O操作完成。在Python中,同步I/O可以被理解为一个被调用的I/O函数会阻塞调用函数的执行。
    • 异步I/O(asynchronous Input/Output operation):
        不会导致请求进程阻塞。可以理解为一个被调用的I/O函数不会阻塞调用函数的执行。
      代码举例如下
    #同步I/O --- 使用HTTPClinet客户端
    from tornado.httpclient import HTTPClient #tornado的同步HTTP客户端类
    print '访问前'
    def syn_visit():
        http_client = HTTPClient()
        print '访问中...'  
        response = http_client.fetch("http://www.lanou3g.com") #阻塞,直到访问完成
        print response.body
    syn_visit()
    print '访问后'
    

    其中,HTTPClinet是tornado的同步访问HTTP客户端。上述代码中的synchronous_visit()函数使用了典型的同步I/O操作访问www.baidu.com网站,该函数的执行时间取决于网络速度、服务器响应速度等,只有对网站访问完成并获取响应结果后,才能完成synchronous_visit()整个函数的执行。

    #异步I/O --- 使用AsyncHTTPClient客户端
    from tornado.httpclient import AsyncHTTPClient #tornado的异步HTTP客户端类
    def handle_response(response):
        print response.body  
    print '访问前'
    def asyn_visit():
        http_client = AsyncHTTPClient()
        print '访问中'
        response = http_client.fetch("http://www.lanou3g.com",callback=handle_response) #不会阻塞进程
    asyn_visit()
    print '访问后'  
    

    其中,AsyncHTTPClient是Tornado的异步访问HTTP客户端。在上述代码中的asyn_visit()函数中使用AsyncHTTPClient对第三方网站进行异步访问,http_client.fetch()函数会在调用后立刻返回而无须等待实际访问的完成,从而导致asyn_visit()也会立刻执行完成。当访问实际完成后,AsyncHTTPClient会调用callback参数指定的函数。
    (2) Python关键字yield
    协程是Tornado中进行异步I/O代码开发的方法。协程使用了Python关键字yield将调用者挂起和恢复执行。所以在学习协程编程之前,首先掌握Python中yield关键字的使用。
      迭代器在Python编程中适用范围很广,那么开发者如何定制自己的迭代器呢?答案就是使用yield关键字。

    当调用任何定义中包含yield关键字的函数都不会执行该函数,而会或得一个对应函数的迭代器。

    示例代码如下图:

    #自定义迭代器函数
    def demoIterator():
        print "The first call of next()"
        yield 'number 1'
        print "The second call of next()"
        yield 'number 2'
        print "The third call of next()"
        yield 'number3'
    print type(demoIterator())  #<type 'generator'>
    for i in demoIterator():
        print i
    

    使用for循环会每次调用迭代器的next()函数,将执行迭代器函数,并返回yield的结果作为迭代返回元素。

    五、协程编程基础

    使用Tornado协程可以开发出类似同步代码的异步行为。同时,因为协程本身不使用线程,所以减少了线程上下文切换的开销。

    1、协程函数的编写
    用协程技术开发网页访问功能,示例代码如下:

    # -*- coding: utf-8 -*-
    from tornado import gen  #引入协程库gen
    from tornado.httpclient import AsyncHTTPClient #引入框架中的异步客户端
    @gen.coroutine
    def cor_visit():
        http_client = AsyncHTTPClient()
        response = yield http_client.fetch('http://www.lanou3g.com')
        print response.body
    

    上述代码中,仍然使用了异步客户端AsyncHTTPClient进行页面访问,修饰器@gen.coroutine声明其是一个协程函数。由于使用了yield关键字,所以代码中不用再编写回调函数用于处理访问结果,而可以直接在yield语句的后面编写结果处理语句。
    2、协程函数的使用
    由于tornado协程基于Python的yield关键字实现,所以不能像调用一般函数去调用。调用协程函数的方式有三种:
    (1) 第一种方式:
    在本身是协程的函数内调用另一个协程函数,可以通过yield关键字调用。

    @gen.coroutine
    def use_cor():
        print "开始调用其它协程函数"
        yield cor_visit()
        print "结束调用其它协程函数"
    

    (2) 第二种方式:
    在IOLoop尚未启动时,通过IOLoop的run_sync()函数。

    from tornado import gen # 引入协程库
    from tornado.ioloop import IOLoop
    from tornado.httpclient import AsyncHTTPClient
    def loop_stop_visit():
        print('开始调用协程')
        IOLoop.current().run_sync(lambda: cor_visit())
        print('结束协程调用')
    loop_stop_visit()
    

    其中,IOLoop 是Tornado的主事件循环对象【IOLoop会在后面有专门的章节去讲解】,Tornado程序通过它监听外部客户端的访问请求,并执行相应的操作,当程序尚未进入IOLoop的runing状态时,可以通过run_sync()函数调用协程函数。run_sync()函数会将阻塞当前函数的执行,直到被调用的协程函数执行完成。
    (2) 第三种方式:
    在IOLoop已经启动时,通过IOLoop的spawn_callback()函数调用。

    def loop_start_visit():
        IOLoop.current().spawn_callback(coroutine_visit)
    loop_start_visit()    #调用
    

    上述代码中,spawn_callback()函数不会等待被调用的协程函数执行完成,所以spawn_callback()之前和之后的语句会被连续执行,而cor_visit本身将会有IOLoop在合适的时机进行调用,并且spawn_callback函数没有为开发者提供获取协程函数调用函数返回值的方法,所以只能用spawn_callback()调用没有返回值的协程函数

  • 相关阅读:
    迭代器在LinkedList上的删除
    java多线程:CopyOnWriteArrayList
    vs中代码编译通过,但还是有红色波浪线
    vs中项目属性配置
    TortoiseGit安装与配置
    DC(device context)
    weak_ptr 使用
    C++ 中shared_ptr循环引用计数问题
    for_each与lambda表达式联合使用
    new 和 make_shared 在内存上的区别
  • 原文地址:https://www.cnblogs.com/mrydblog/p/mryd.html
Copyright © 2020-2023  润新知