• [原]tornado源码分析系列(一)[tornado简介]


    引言:

      tornado是由Facebook开源的一个服务器“套装",适合于做python的web或者使用其本身提供的可扩展的功能,完成了不完整的wsgi协议,可用于做快速的web开发,封装了epoll性能较好。文章主要以分析tornado的网络部分即异步事件处理与上层的IOstream类提供的异步IO,其他的模块如web的tornado.web 以后慢慢留作分析。

    首先说明几点问题:

    (1)文章供大家交流使用,如果有错误,发扬开源精神,共同交流

    (2)文章不加以说明,均以Linux环境为例

    (3)如果有epoll,tornado默认使用epoll,这里就不分析select和KQueue了

    (4)请不要再问为什么使用python来作为网络库而不是高效的C/C++了,因为对于IO密集型程序来说,上层语言的程序运行差异没有那么大,而且tornado中使用的epoll部分也是用C来写的。

    下面开始我们的tornado之旅,看源代码之前必定需要有一份源码了,大家可以去官网下载一份。

    一.源码组织:

      |---__init__.py

       ---auth.py

       ---......

       ---epoll.c

       ---ioloop.py

       ---iostream.py

       ---...

      tornado网络部分最核心的两个模块就是ioloop.py与iostream.py,我们主要分析的就是这两个部分。

      ioloop.py 主要的是将底层的epoll或者说是其他的IO多路复用封装作异步事件来处理

      iostream.py主要是对于下层的异步事件的进一步封装,为其封装了更上一层的buffer(IO)事件

      很好的一点就是在tornado的源码中,都提供了一个简单的Demo,我就以这些Demo为例来讲,再多的话也不如看代码,程序猿最好的交流方式就是看代码。

      

            import errno
            import functools
            import ioloop
            import socket
    
            def connection_ready(sock, fd, events):
                while True:
                    try:
                        connection, address = sock.accept()
                    except socket.error, e:
                        if e.args[0] not in (errno.EWOULDBLOCK, errno.EAGAIN):
                            raise
                        return
                    connection.setblocking(0)
                    handle_connection(connection, address)
    
            sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0)
            sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
            sock.setblocking(0)
            sock.bind(("", port))
            sock.listen(128)
    
    #创建一个ioloop 实例
            io_loop = ioloop.IOLoop.instance()
    #冻结 connection_ready 的第一个参数为 sock ,既 socket 的返回值
            callback = functools.partial(connection_ready, sock)
    #注册函数,  第一个参数是将 sock 转换为标准的描述符,第二个为回调函数,第三个是事件类型        
            io_loop.add_handler(sock.fileno(), callback, io_loop.READ)
    #开始~
            io_loop.start()
    

    可以看到在注释前都是使用了传统的创建服务器的方式,不用多介绍,注意就是把套接口设置为非阻塞方式

    创建ioloop实例,这里是使用了ioloop.IOLoop中的 instance()静态方法,以 @classmethod 方式包装

    在后面的add_handler中,程序为我们的监听套接口注册了一个回调函数和一个事件类型

    工作方式是这样,在注册了相应的事件类型和回调函数以后,程序开始启动,如果在相应的套接口上有事件发生(注册的事件类型)那么调用相应的回调函数

    代码通俗易懂 

    当监听套接口有可读事件发生,意味着来了一个新连接,在回调函数中就可以对这个套接口accept,并调用相应的处理函数,其实应该是处理函数也设置为异步的,将相应的连接套接口也加入到事件循环并注册相应的回调函数,只是这里没有展示出来。

    在使用非阻塞方式的accept时候常常返回EAGAIN,EWOULDBLOCK 错误,这里采取的方式是放弃这个连接。

     总结:以这样的方式开始了源码分析觉得挺水的,第一篇文章就以短小精干为起点了,广交志同道合人士。

    文章属原创,转载请注明出处 联系作者: Email:zhangbolinux@sina.com QQ:513364476
  • 相关阅读:
    算法很美(一)
    pytest学习(四)
    pytest学习(三)
    pytest学习(二)
    pytest学习(一)
    HTTP协议详细介绍,面试详全强助攻!
    Docker实战总结
    微信小程序测试整理
    这些用例设计题,你在面试时遇到过吗?
    测试面试题集-Dubbo常见面试题(12)
  • 原文地址:https://www.cnblogs.com/Bozh/p/2596458.html
Copyright © 2020-2023  润新知