欢迎访问皮皮网官网
皮皮网

【solr 4.7.2源码】【特斯拉盗源码】【ug源码优化】tornado 源码

时间:2024-12-28 16:36:59 分类:热点 来源:j值公式源码

1.如何理解 Tornado
2.Tornado主要特点
3.UNIX环境高级编程UNIX网络编程12这三本书先看哪个一个?网络编程和web编程疑惑,pythontornado源码学习
4.为什么选择tornado作为web开发框架?
5.Tornado之ioloop源码学习

tornado 源码

如何理解 Tornado

       å‡è®¾ä½ è¿˜ä¸çŸ¥é“Tornado是什么也不知道为什么应该对它感兴趣,那我将用简短的话来介绍Tornado这个项目。如果你已经对它有了兴趣,你可以跳去看下一节内容。

       Tornado是一个用Python编写的异步HTTP服务器,同时也是一个web开发框架。该框架服务于FriendFeed网站,最近Facebook也在使用它。FriendFeed网站有用户数多和应用实时性强的特点,所以性能和可扩展性是很受重视的。由于现在它是开源的了(这得归功于Facebook),我们可以彻底的对它是如何工作的一探究竟。

       æˆ‘觉得对非阻塞式IO (nonblocking IO) 和异步IO (asynchronous IO AIO)很有必要谈一谈。如果你已经完全知道他们是什么了,可以跳去看下一节。我尽可能的使用一些例子来说明它们是什么。

       è®©æˆ‘们假设你正在写一个需要请求一些来自其他服务器上的数据(比如数据库服务,再比如新浪微博的open api)的应用程序,然后呢这些请求将花费一个比较长的时间,假设需要花费5秒钟。大多数的web开发框架中处理请求的代码大概长这样:

       def handler_request(self, request):

        answ = self.remote_server.query(request) # this takes 5 seconds

        request.write_response(answ)

       å¦‚果这些代码运行在单个线程中,你的服务器只能每5秒接收一个客户端的请求。在这5秒钟的时间里,服务器不能干其他任何事情,所以,你的服务效率是每秒0.2个请求,哦,这太糟糕了。

       å½“然,没人那么天真,大部分服务器会使用多线程技术来让服务器一次接收多个客户端的请求,我们假设你有个线程,你将在性能上获得倍的提高,所以现在你的服务器效率是每秒接受4个请求,但这还是太低了,当然,你可以通过不断地提高线程的数量来解决这个问题,但是,线程在内存和调度方面的开销是昂贵的,我怀疑如果你使用这种提高线程数量的方式将永远不可能达到每秒个请求的效率。

       å¦‚果使用AIO,达到每秒上千个请求的效率是非常轻松的事情。服务器请求处理的代码将被改成这样:

       def handler_request(self, request):

        self.remote_server.query_async(request, self.response_received)

       def response_received(self, request, answ): # this is called 5 seconds later

        request.write(answ)

       AIO的思想是当我们在等待结果的时候不阻塞,转而我们给框架一个回调函数作为参数,让框架在有结果的时候通过回调函数通知我们。这样,服务器就可以被解放去接受其他客户端的请求了。

       ç„¶è€Œè¿™ä¹Ÿæ˜¯AIO不太好的地方:代码有点不直观了。还有,如果你使用像Tornado这样的单线程AIO服务器软件,你需要时刻小心不要去阻塞什么,因为所有本该在当前返回的请求都会像上述处理那样被延迟返回。

       å…³äºŽå¼‚æ­¥IO,比当前这篇过分简单的介绍更好的学习资料请看 The CK problem。

       æºä»£ç 

       è¯¥é¡¹ç›®ç”±github托管,你可以通过如下命令获得,虽然通过阅读这篇文章你也可以不需要它是吧。

       git clone git://github.com/facebook/tornado.git

       åœ¨tornado的子目录中,每个模块都应该有一个.py文件,你可以通过检查他们来判断你是否从已经从代码仓库中完整的迁出了项目。在每个源代码的文件中,你都可以发现至少一个大段落的用来解释该模块的doc string,doc string中给出了一到两个关于如何使用该模块的例子。

       IOLoop模块

       è®©æˆ‘们通过查看ioloop.py文件直接进入服务器的核心。这个模块是异步机制的核心。它包含了一系列已经打开的文件描述符(译者:也就是文件指针)和每个描述符的处理器(handlers)。它的功能是选择那些已经准备好读写的文件描述符,然后调用它们各自的处理器(一种IO多路复用的实现,其实就是socket众多IO模型中的select模型,在Java中就是NIO,译者注)。

       å¯ä»¥é€šè¿‡è°ƒç”¨add_handler()方法将一个socket加入IO循环中:

       def add_handler(self, fd, handler, events):

        """Registers the given handler to receive the given events for fd."""

        self._handlers[fd] = handler

        self._impl.register(fd, events | self.ERROR)

       _handlers这个字典类型的变量保存着文件描述符(其实就是socket,译者注)到当该文件描述符准备好时需要调用的方法的映射(在Tornado中,该方法被称为处理器)。然后,文件描述符被注册到epoll(unix中的一种IO轮询机制,貌似,译者注)列表中。Tornado关心三种类型的事件(指发生在文件描述上的事件,译者注):READ,WRITE 和 ERROR。正如你所见,ERROR是默认为你自动添加的。

       self._impl是select.epoll()和selet.select()两者中的一个。我们稍后将看到Tornado是如何在它们之间进行选择的。

       çŽ°åœ¨è®©æˆ‘们来看看实际的主循环,不知何故,这段代码被放在了start()方法中:

       def start(self):

        """Starts the I/O loop.

        The loop will run until one of the I/O handlers calls stop(), which

        will make the loop stop after the current event iteration completes.

        """

        self._running = True

        while True:

        [ ... ]

        if not self._running:

        break

        [ ... ]

        try:

        event_pairs = self._impl.poll(poll_timeout)

        except Exception, e:

        if e.args == (4, "Interrupted system call"):

        logging.warning("Interrupted system call", exc_info=1)

        continue

        else:

        raise

        # Pop one fd at a time from the set of pending fds and run

        # its handler. Since that handler may perform actions on

        # other file descriptors, there may be reentrant calls to

        # this IOLoop that update self._events

        self._events.update(event_pairs)

        while self._events:

        fd, events = self._events.popitem()

        try:

        self._handlers[fd](fd, events)

        except KeyboardInterrupt:

        raise

        except OSError, e:

        if e[0] == errno.EPIPE:

        # Happens when the client closes the connection

        pass

        else:

        logging.error("Exception in I/O handler for fd %d",

        fd, exc_info=True)

        except:

        logging.error("Exception in I/O handler for fd %d",

        fd, exc_info=True)

       poll()方法返回一个形如(fd: events)的键值对,并赋值给event_pairs变量。由于当一个信号在任何一个事件发生前到来时,C函数库中的poll()方法会返回EINTR(实际是一个值为4的数值),所以"Interrupted system call"这个特殊的异常需要被捕获。更详细的请查看man poll。

       åœ¨å†…部的while循环中,event_pairs中的内容被一个一个的取出,然后相应的处理器会被调用。pipe 异常在这里默认不进行处理。为了让这个类适应更一般的情况,在http处理器中处理这个异常是一个更好的方案,但是选择现在这样处理或许是因为更容易一些。

       æ³¨é‡Šä¸­è§£é‡Šäº†ä¸ºä»€ä¹ˆä½¿ç”¨å­—典的popitem()方法,而不是使用更普遍一点的下面这种做法(指使用迭代,译者注):

       for fd, events in self._events.items():

       åŽŸå› å¾ˆç®€å•ï¼Œåœ¨ä¸»å¾ªçŽ¯æœŸé—´ï¼Œè¿™ä¸ª_events字典变量可能会被处理器所修改。比如remove_handler()处理器。这个方法把fd(即文件描述符,译者注)从_events字典中取出(extracts,意思是取出并从_events中删除,译者注),所以即使fd被选择到了,它的处理器也不会被调用(作者的意思是,如果使用for迭代循环_events,那么在迭代期间_events就不能被修改,否则会产生不可预计的错误,比如,明明调用了remove_handler()方法删除了某个<fd, handler>键值对,但是该handler还是被调用了,译者注)。

Tornado主要特点

       Tornado的独特之处在于其灵活的开发工具适用性,无论是在应用开发的哪个阶段,还是在不同硬件环境下,都能得心应手。完整的solr 4.7.2源码Tornado工具集使得开发者无需过多考虑连接策略或存储需求,专注于核心开发工作。

       Tornado结构设计初衷是为开发者和第三方工具厂商提供一个开放的平台。已经存在的一系列API接口,包括开发环境接口和连接实现,为开发者提供了丰富的资源和参考文档。

       尤其值得一提的是,Tornado提供了强大的开发和调试工具,如C和C++源码级别的调试器、目标和工具管理、系统目标跟踪、内存使用分析以及自动配置,这些工具特别适合解决嵌入式开发中的复杂问题,支持高效的协同开发。

       VxWorks支持工业标准,如实时扩展的POSIX .1b、ANSI C(含浮点支持)以及TCP/IP网络协议,特斯拉盗源码这些标准增强了不同产品间的兼容性,提升了系统的可移植性,保护了用户的开发和培训投资。

       VxWorks拥有一个高效的微内核,支持实时系统的多任务、中断管理、抢占式和循环调度等特性。这种设计显著减少了系统开销,加快了对外部事件的响应。例如,在K处理器上,上下文切换仅需3.8微秒,中断等待时间更是少于3微秒,显示了其运行速度和确定性。

       更重要的是,VxWorks的可扩展性非常出色。开发者可以根据应用需求动态分配资源,从最小的嵌入设计到复杂的高端实时应用,它提供了多达种不同的配置选项,供开发者选择。

       例如,ug源码优化IBM的rational time realtest就选择了VxWorks作为其开发平台,这进一步证明了VxWorks的强大功能和灵活性。

扩展资料

       系统内容 TornadoTornado代表嵌入实时应用中最新一代的开发和执行环境。 Tornado 包含三个完整的部分: (1)Tornado系列工具, 一套位于主机或目标机上强大的交互式开发工具和使用程序; (2)VxWorks 系统, 目标板上高性能可扩展的实时操作系统; (3)可选用的连接主机和目标机的通讯软件包 如以太网、串行线、在线仿真器或ROM仿真器。

UNIX环境高级编程UNIX网络编程这三本书先看哪个一个?网络编程和web编程疑惑,pythontornado源码学习

       接触Python Web开发一年,疑惑丛生,主要涉及进程、线程编程及网络编程。在实际项目中,应如何正确运用进程和线程?对网络编程的深入理解,特别是高性能服务器设计实现,感到困惑,尤其是面对Tornado服务器代码,难以理解。

       关于UNIX环境高级编程、UNIX网络编程(卷1、课堂作文源码2)这三本书的阅读顺序,应先从基础知识入手。推荐先阅读《图解TCP/IP》一书,把握面向连接与无连接、TCP粘包与UDP有界等核心概念。紧接着,深入学习Linux/Unix系统编程手册中关于socket的章节,这本书以超越apue的讲解方式,对socket、select、poll、epoll等关键概念进行了详细解析,有助于理解并发编程原理。

       了解并阅读Tornado源码,这一阶段应较为轻松,因为之前对相关概念和原理已有基础理解。《Effective TCP/IP》一书则提供了更高级的指导,帮助深化对网络编程的理解。最后推荐阅读《UNIX网络编程》(卷1),尽管其内容丰富,但先阶段主要关注其基本网络模型的cpld源码参考介绍,如多进程、多线程版本的echo服务器程序、非阻塞web客户端程序等,这有助于初步构建对网络编程的实践认知。

       理解高性能服务器的实现,源码阅读是关键。例如,学习lighttpd的IO复用技术。在进程线程编程方面,理解操作系统级别的概念同样重要。网络编程确实涉及众多复杂概念,但通过持续学习和实践,能力将逐步提升。在自学过程中,任何疑惑与不解,欢迎向社区或专业人士求教,共同进步。

为什么选择tornado作为web开发框架?

       Tornado框架之所以被知乎选中,关键在于其异步非阻塞的I/O模型,特别适合处理大量Comet长轮询连接,这与FriendFeed开发Tornado的初衷不谋而合。知乎同样需要实时更新动态信息流,而Comet技术能有效满足这一需求。选择Tornado,对知乎来说,是一次技术上的精准对接。

       然而,Tornado并非全能。其单线程模型意味着当请求阻塞I/O时,进程将无法处理新请求或完成其他阻塞请求,类似PHP FastCGI进程的运行方式。处理会阻塞I/O的请求通常会借助Tornado内置的异步HTTP客户端,转而由其他动态后端执行。

       因此,在实际应用中,Tornado常与Nginx结合使用,Nginx负责处理静态文件等大量I/O操作,以充分利用Tornado的高效I/O特性。Tornado的I/O时间成本高昂,不宜过多用于此类操作。

       针对性能测试,实际上应用中的逻辑处理会阻塞I/O,这将严重影响Tornado性能。在测试代码前加入模拟阻塞的指令,可以直观地观察性能变化。至于Tornado文档不足的问题,阅读其源代码会是一个高效的学习途径,因为代码清晰且注释详尽,容易理解。

       记住,利用原生异步特性是发挥Tornado优势的关键。虽然Tornado自带的MySQL库不是异步的,可能导致性能瓶颈,但通过异步调用的简化,gen等工具依然能提高开发效率。在实际应用中,确保所有调用异步化,才能真正释放Tornado的潜力。

Tornado之ioloop源码学习

       在闲暇之余,我研究了tornado的源码,并计划以系列文章的形式记录关键部分,旨在总结学习心得并可能对使用该框架的朋友有所帮助。如有疏漏,欢迎私信或评论指正。

       在研究开源项目时,我通常选择原始版本的tornadoweb/tornado,因为我认为其核心功能通常在1.0.0版本就已经完备,后续的改进主要集中在细节,而非重大功能。代码风格的统一性可能会因不同开发者提交的代码而有所差异。

       在阅读之前,我建议您对Linux的IO模型有所了解,特别是epoll和kqueue(在Mac或BSD系统中)的概念。Python 2.6及以上版本的select库提供了相关实现,但2.6以下版本则需要依赖tornado对底层epoll的封装。以下代码正是处理这个选择过程的。

       接下来,让我们深入探讨tornado的内部。首先,我们关注的是底层的 epoll 实现,如 GitHub 上的代码。它提供了常规的epoll功能,熟悉该技术的开发者一眼就能看懂。

       然后是 IOLoop 类,我们从头开始分析。其中定义了 epoll 中的关键事件,如 _EPOLLIN 和 _EPOLLOUT,分别表示文件描述符的读写就绪状态。

       在代码中,_set_close_exec 方法的作用是解决子进程 fork 后可能遇到的问题。当子进程仅被 fork 并执行 exec 时,原有的文件描述符可能会消失,这个方法确保在 exec 时关闭这些描述符。

       r, w = os.pipe() 则创建了一个管道,用于高效地中断 IOLoop 循环。当管道另一端写入数据时,会阻塞 poll() 方法,从而停止循环。

       此外,IOLoop 通过 signal 模块监控 block 时间,当超过设定时间,将执行预先定义的 handler。信号 SIGALRM 和 ITIMER_REAL 通常一起使用。

       至关重要的 start 方法下,有几个辅助方法。_callbacks 存储了将在下一次 IOLoop 循环前调用的函数,保证跨线程安全。相比之下,_timeouts 保存了执行函数和截止时间的对应关系,允许延迟执行。

       关于 poll_timeout 的设置,它决定了 IOLoop 等待就绪事件的时间。默认值为 0.2 秒,如果存在可以执行的回调,会调整为尽快执行。最后,IOLoop 通过 poll 函数获取就绪事件,使用 signal.ITIMER_REAL 进行计时,处理后利用 pop 方法而非遍历,避免映射关系在处理过程中变化。

       以上就是对 IOLoop 的基本介绍,期待你的反馈和指正。

copyright © 2016 powered by 皮皮网   sitemap