1.å¦ä½ç解 Tornado
2.Tornado主要特点
3.UNIX环境高级编程UNIX网络编程12这三本书先看哪个一个?网络编程和web编程疑惑,pythontornado源码学习
4.为什么选择tornado作为web开发框架?
5.Tornado之ioloop源码学习
å¦ä½ç解 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的独特之处在于其灵活的开发工具适用性,无论是在应用开发的哪个阶段,还是在不同硬件环境下,都能得心应手。完整的idea tomcat 源码Tornado工具集使得开发者无需过多考虑连接策略或存储需求,专注于核心开发工作。 Tornado结构设计初衷是为开发者和第三方工具厂商提供一个开放的平台。已经存在的一系列API接口,包括开发环境接口和连接实现,为开发者提供了丰富的资源和参考文档。 尤其值得一提的是,Tornado提供了强大的开发和调试工具,如C和C++源码级别的调试器、目标和工具管理、系统目标跟踪、内存使用分析以及自动配置,这些工具特别适合解决嵌入式开发中的复杂问题,支持高效的协同开发。 VxWorks支持工业标准,如实时扩展的POSIX .1b、ANSI C(含浮点支持)以及TCP/IP网络协议,钻石买入公式源码这些标准增强了不同产品间的兼容性,提升了系统的可移植性,保护了用户的开发和培训投资。 VxWorks拥有一个高效的微内核,支持实时系统的多任务、中断管理、抢占式和循环调度等特性。这种设计显著减少了系统开销,加快了对外部事件的响应。例如,在K处理器上,上下文切换仅需3.8微秒,中断等待时间更是少于3微秒,显示了其运行速度和确定性。 更重要的是,VxWorks的可扩展性非常出色。开发者可以根据应用需求动态分配资源,从最小的嵌入设计到复杂的高端实时应用,它提供了多达种不同的配置选项,供开发者选择。 例如,oa免费系统源码IBM的rational time realtest就选择了VxWorks作为其开发平台,这进一步证明了VxWorks的强大功能和灵活性。扩展资料
系统内容 TornadoTornado代表嵌入实时应用中最新一代的开发和执行环境。 Tornado 包含三个完整的部分: (1)Tornado系列工具, 一套位于主机或目标机上强大的交互式开发工具和使用程序; (2)VxWorks 系统, 目标板上高性能可扩展的实时操作系统; (3)可选用的连接主机和目标机的通讯软件包 如以太网、串行线、在线仿真器或ROM仿真器。UNIX环境高级编程UNIX网络编程这三本书先看哪个一个?网络编程和web编程疑惑,pythontornado源码学习
接触Python Web开发一年,疑惑丛生,主要涉及进程、线程编程及网络编程。在实际项目中,应如何正确运用进程和线程?对网络编程的深入理解,特别是高性能服务器设计实现,感到困惑,尤其是面对Tornado服务器代码,难以理解。
关于UNIX环境高级编程、UNIX网络编程(卷1、.net core 1.0源码2)这三本书的阅读顺序,应先从基础知识入手。推荐先阅读《图解TCP/IP》一书,把握面向连接与无连接、TCP粘包与UDP有界等核心概念。紧接着,深入学习Linux/Unix系统编程手册中关于socket的章节,这本书以超越apue的讲解方式,对socket、select、poll、epoll等关键概念进行了详细解析,有助于理解并发编程原理。
了解并阅读Tornado源码,这一阶段应较为轻松,因为之前对相关概念和原理已有基础理解。《Effective TCP/IP》一书则提供了更高级的指导,帮助深化对网络编程的理解。最后推荐阅读《UNIX网络编程》(卷1),尽管其内容丰富,但先阶段主要关注其基本网络模型的源码文件的格式介绍,如多进程、多线程版本的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 的基本介绍,期待你的反馈和指正。